home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / CRS / crs50.d81 / issue11 < prev    next >
Text File  |  2009-10-10  |  172KB  |  3,875 lines

  1.                    ########
  2.              ##################
  3.          ######            ######
  4.       #####
  5.     #####  ####  ####      ##      #####   ####  ####  ####  ####  ####   #####
  6.   #####    ##    ##      ####    ##   ##   ##  ###     ##    ####  ##   ##   ##
  7.  #####    ########     ##  ##   ##        #####       ##    ## ## ##   ##
  8. #####    ##    ##    ########  ##   ##   ##  ###     ##    ##  ####   ##   ##
  9. #####  ####  ####  ####  ####  #####   ####  ####  ####  ####  ####   ######
  10. #####                                                                     ##
  11.  ######            ######            Issue #11
  12.    ##################               Version 1.0
  13.        ########                    December 1995
  14.  
  15. -------------------------------------------------------------------------------
  16.  
  17. #(@)contents: Table of Contents
  18.  
  19.  
  20. Features
  21.    6. Speed up RAMLink transfers with the Double-DMA Technique
  22.       (Reference: dbldma)                   by Doug Cotton and Mark Fellows 
  23.         RAMLink Designer Mark Fellows and Technical Editor Doug Cotton of 
  24.         CMD describe a way of using a Commodore REU to increase transfer 
  25.         rates of the CMD RAMLink to one-half the speed of the REU transfer 
  26.         rate.
  27.    8. The Graphics Toolbox by Stephen Judd
  28.       (Reference: toolbox)
  29.         To add another tool to our toolbox, Stephen details a new algorithm
  30.         for drawing ellipses.  Some improvements to the circle routine in
  31.         a previous column that will enable it to draw perfect circles of any
  32.         radius is discussed, as well as details on using logarithms to 
  33.         perform division.
  34.   10. Design and Implementation of an Advanced Text Editor by Craig Bruce
  35.       (Reference: zedace)
  36.         Peer into the internal organization and implementation of an 
  37.         advanced text editor/word processor for the ACE environment. 
  38.         Relevant data structure, global variables, display maintenance, 
  39.         text "sloshing", and algorithms for many editing commands are 
  40.         detailed.
  41.  
  42. Columns
  43.    4. Hi Tech Trickery by George Taylor
  44.       (Reference: trick)
  45.         Don't let anyone ever tell you the SID chip is only capable of 4 bit 
  46.         sample playback.  George Taylor explains using the digi dithering 
  47.         technique to increase the SID's resolution.
  48.   12. Hacking Graphics by Rick Mosdell
  49.       (Reference: gfx)
  50.         Dig into this overview on how to set up the VIC-II to display Doodle
  51.         and KOALA format pictures.  The two formats are detailed, and similar
  52.         formats are referenced.
  53.    
  54. Departments
  55.    1. The (cough,cough) Hacking Editor
  56.       (Reference: editor)
  57.    2. Input/Output
  58.       (Reference: io)
  59.    3. Newsfront
  60.       (Reference: news)
  61.    5. Hacking the Mags
  62.       (Reference: mags)
  63.    7. UseNuggets
  64.       (Reference: usenet)
  65.    9. Hack Surfing
  66.       (Reference: surf)
  67.   11. Commodore Trivia
  68.       (Reference: trivia)
  69.   13. ? DS, DS$: rem The Error Channel
  70.       (Reference: error)
  71.   14. The Next Hack
  72.       (Reference: next)
  73.  
  74. -------------------------------------------------------------------------------
  75.  
  76. #(@)legal: Commodore Hacking Legal Notice
  77.  
  78. Commodore and the respective Commodore product names are trademarks or 
  79. registered trademarks of ESCOM GmbH.  Commodore hacking is in no way 
  80. affiliated with ESCOM GmbH, owners of said trademarks.  Commodore Hacking is 
  81. published 4 times yearly by:
  82.  
  83. Brain Innovations Inc. 
  84. 602 N. Lemen 
  85. Fenton MI  48430
  86.  
  87. The magazine is published on on-line networks free of charge, and a nominal 
  88. fee is charged for alternate mediums of transmission.  
  89.  
  90. Permission is granted to re-distribute this "net-magazine" or "e-zine" in its 
  91. entirety for non-profit use.  A charge of no more than US$5.00 may be 
  92. charged by redistribution parties to cover printed duplication and no more
  93. than US$10.00 for other types of duplication to cover duplication and media
  94. costs for this publication.  If this publication is included in a for-profit 
  95. compilation, this publication must be alternately available separately or as
  96. part of a non-profit compilation.
  97.  
  98. This publication, in regards to its specific ordering and compilations of
  99. various elements, is copyright(c) 1995 by Brain Innovations, Incorporated,
  100. unless otherwise noted.  Each work in this publication retains any and all 
  101. copyrights pertaining to the individual work's contents.  For  
  102. redistribution rights to individual works, please contact the author of said 
  103. work or Brain Innovations, Inc.
  104.  
  105. Brain Innovations, Inc. assumes no responsibility for errors or omissions in 
  106. editorial, article, or program listing content.  
  107.  
  108. -------------------------------------------------------------------------------
  109.  
  110. #(@)info: Commodore Hacking Information
  111.  
  112. Commodore Hacking is published via the Internet 4 times yearly, and is 
  113. presented in both ISO-8859-1 and HTML versions.  This and previous issues can 
  114. be found at the Commodore Hacking Home Page 
  115. (http://www.msen.com/~brain/chacking/), as well as via FTP 
  116. (ftp://ccnga.uwaterloo.ca/pub/cbm/hacking.mag/)
  117.  
  118. In addition, the Commodore Hacking mail server can be used to retrieve each 
  119. issue.  To request a copy of an issue, please send the following electronic 
  120. mail message:
  121.  
  122. To: brain@mail.msen.com
  123. Subject: MAILSERV
  124. Body of Message:
  125.  
  126. help
  127. catalog
  128. send c=hacking11.txt 
  129. quit
  130.  
  131. To subscribe to the Commodore Hacking and receive new issues as 
  132. they are published, add the following command to you MAILSERV message 
  133. prior to the quit command:
  134.  
  135. subscribe c=hacking Firstname Lastname msglen
  136.  
  137. (msglen is largest size of file in kilobytes you can receive in an email 
  138. message.  When in doubt, choose 64)
  139.  
  140. example:
  141.  
  142. subscribe c=hacking Jim Brain 100
  143.  
  144. Although no fee is charged for this magazine, donations are gladly accepted 
  145. from corporate and individual concerns.  All monies will be used to defray 
  146. any administrative costs, subscribe to publications for review, and 
  147. compensate the individual authors contributing to this issue.
  148.  
  149. Any persons wishing to author articles for inclusion in Commodore Hacking are 
  150. encouraged to view the submission guidelines on the WWW
  151. (http://www.msen.com/~brain/pub/c-hacking-submit.txt) or via the MAILSERV 
  152. server (send c-hacking-submit.txt).  
  153.  
  154. ============================================================================
  155.  
  156. #(@)rch: Reading C=Hacking
  157.  
  158. Starting with Issue 11 of Commodore Hacking, the new QuickFind indexing 
  159. system is utilized to aid readers of the text version in navigating the
  160. magazine.  At the top  of each article or other important place in the
  161. magazine, a word prefixed with a special string is present.  (See the
  162. title of this article for an example.  Throughout the magazine, if an
  163. article is mentioned, it will be followed by a reference string.  For
  164. example, if we mentioned this article, we would add (Reference: rch) after
  165. the name.  By using your favorite editor's search function and searching
  166. for the string after the word "Reference:", prefixed by the magic prefix
  167. string, will move you directly to the article of choice.  To merely skip to
  168. the next article in the magazine, search only for the magic prefix string.
  169.  
  170. Some handy indexing strings possibly not referenced anywhere are:
  171.  
  172. top      top of issue
  173. bottom   bottom of issue
  174. contents table of contents
  175. legal    legal notice
  176.  
  177. For those with access to a UNIX system, the command "what" can be
  178. run on the issue, which will result in all the article titles being
  179. printed.
  180.  
  181. A slightly different magic prefix string "#(A)" is used to delimit
  182. sub-topics or main heading in articles.  The text after the magic string
  183. differs depending on article content.  For the Input/Output column
  184. (Reference: io), the text after the magic prefix will either be "c" for 
  185. comment, or "r" for response.  In features and columns, a number after
  186. the prefix indicates the ordinal of that heading or sub-topic in the
  187. article.  If a specific sub-topic is referenced elsewhere in the article,
  188. a sub-topic reference will be indicated.  A reference to "#(A)r" would
  189. be written as "(SubRef: r)".
  190.  
  191. As time goes on, the role of this indexing system will be expanded and
  192. changed to ease navigation of the text version, but minimize the clutter
  193. added by these extra items.
  194.  
  195. ============================================================================
  196.  
  197. #(@)editor: The Hacking Editor
  198.             by Jim Brain (brain@mail.msen.com)
  199.  
  200. Two new faces appear in this month's Commodore Hacking.  One is its new editor,
  201. while the other is its new look.  I hope neither causes anyone to worry about 
  202. the content of the magazine.  It's all still here.  C=Hacking will continue
  203. to provide leading edge technical information about the Commodore computers
  204. we all know and love.  The magazine will continue to cater to the Commodore
  205. computer programmer, whether it be in the areas of sound, graphics, algorithms,
  206. disk media access, or communications.  
  207.  
  208. However, the role of the magazine continues to expand.  It has been shown that
  209. many people other than CBM programmers read the magazine, and programmers have
  210. requested other information besides technical content be included in the
  211. magazine.  To this end, Issue 11 contains many new features, including:
  212.  
  213. o  "Hacking the Mags" (Reference: mags), which will summarize the other 
  214.    Commodore magazines in the market place.  Not everyone can read or
  215.    subscribe to all the quality CBM publications out there, so this column
  216.    will alert readers to specific issues that may be of interest.
  217.    
  218. o  "Newsfront" (Reference: news), which will bring the Commodore programmer 
  219.    and user up to date on developments in the Commodore community.  The
  220.    Commodore world doesn't stand still, and every programmer should be aware
  221.    of the newest technologies affecting the CBM line.
  222.  
  223. o  "The Error Channel" (Reference: error), which will formalize the process 
  224.    of fixing errors in earlier issues.  Hopefully, this will be unnecessary
  225.    in most issues, but it will be here just in case.
  226.    
  227. o  "Input/Output" (Reference: io), which will allow C=Hacking readers space 
  228.    for comments and concerns.  Many readers have sent me suggestions and
  229.    comments, some C=Hacking can implement, and some C=Hacking cannot.  
  230.    This spot will detail which is which and why.
  231.  
  232. o  Article separators.  As you can see above, each article or column in the
  233.    magazine is delimited by the special key, followed by a short name
  234.    of the article.  See "Reading C=Hacking" (Reference: rch) in this issue.
  235.    
  236. o  Smaller size.  The last issue was over 400kB in size, which generated
  237.    many complaints.  There is no need to create such a long issue, when 
  238.    more issues can be published.  This issue should comfortably fit on
  239.    two sides of a 1541 disk, a 1571 disk, or a 1581 disk.
  240.  
  241. o  Stable publication dates.  Circumstances (college, job hunt), made it 
  242.    hard for the previous editor to maintain a schedule, so no blame is laid,
  243.    but the magazine does need some stability.  Although possibly unrealistic,
  244.    I am striving to publish C=Hacking quarterly, with the following schedule:
  245.       
  246.       Publication Date        Submission Deadline
  247.       March, 1996             February 10, 1996
  248.       June, 1996              May 10, 1996
  249.       September, 1996         Auguest 10, 1996
  250.       December 1996           November 10, 1996
  251.  
  252.    If article submissions keep up, a switch to bi-monthly publication might
  253.    be warranted, but I won't get too far ahead.
  254.    
  255. o  Fully HTML-ized version of the magazine.  Issue 11 contains many
  256.    improvements designed to make the publication of an World Wide Web
  257.    readable version of the magazine easier.  Look for the HTML version of
  258.    this and older issues at URL: http://www.msen.com/~brain/chacking/.   
  259.    
  260. Many people have compared Commodore Hacking to the defunct _Transactor_ 
  261. magazine, which is encouraging.  The new format will hopefully add to the
  262. appeal of Commodore Hacking.
  263.  
  264. Although many of you know me or of me through previous Commodore work, this
  265. is my first editorship, so please comment on the changes I have made and what
  266. your opinions on each are.  As the magazine is for you, the reader, it is
  267. always important to keep the reader happy.
  268.  
  269. Sadly, some things, like the WWW browser for C=Hacking, did not get done,
  270. but there is always next time.
  271.  
  272. Enjoy YOUR magazine,
  273.  
  274. Jim Brain (brain@mail.msen.com)
  275. editor
  276.  
  277. ============================================================================
  278.  
  279. #(@)io: Input/Ouput
  280.  
  281. Obviously, Commodore Hacking depends on the comments and article submissions
  282. from the Commodore community to flourish.  Everyone sees the articles, but
  283. let's not forget those comments.  They are very helpful, and every attempt
  284. is made to address concerns in them.  Address any comments, concerns, or
  285. suggestions to:
  286.  
  287. Commodore Hacking
  288. 602 N. Lemen
  289. Fenton, MI  48430
  290. brain@mail.msen.com (Internet)
  291.  
  292. #(A)c: Need Samples of Samples  
  293.  
  294. From: "Clifford \"Paska\" Anderson" <andersoc@saturn.uaamath.alaska.edu>
  295.  
  296. Dear C=Hacking,
  297. Hey.  Just writing to mention something I'd like to see in C=Hacking, if 
  298. you can find someone to write about it.  I am interested in knowing more 
  299. about how samples work on the 64, how to play, etc.
  300. -----
  301.  _    _       _
  302. Si vales, valeo
  303.  
  304. #(A)r:
  305. Your wish is granted.  Check out this issue's Hi Tech Trickery 
  306. (Reference: trick) by George Taylor for some insight into playing 
  307. samples.
  308.  
  309. #(A)c: You Index, I Index, We all Index
  310.  
  311. From: coyote@wakko.gil.net
  312.  
  313. Dear C=Hacking,
  314. I would like to offer an idea for the Chacking mag. Every now and then 
  315. I'll come across a reference to an article in this or that Chacking Issue.
  316. I run Zed and load that issue in (Thanks Mr Bruce) and start hunting for 
  317. the start of the article. 
  318.  
  319. This process would be made a lot easier if Chacking used a method of 
  320. indexing I have seen used in several publications.
  321.  
  322. It involves the search function of most text editors. A 2/3/4 ? letter 
  323. code (with a delimiter char to prevent unintentional matches) that the 
  324. reader uses to find the beginning of the article.
  325.  
  326. (Outline of suggestion deleted)
  327.  
  328. I would like to add a personal thanks for all your efforts on behalf of 
  329. the C= community.
  330.  
  331. Al Anger
  332. 13841 SW 139 Ct.
  333. Miami Fl. 33186
  334. (305) 233-4689
  335.  
  336. #(A)r:
  337. Fire up that search function in your favorite editor.  Issue 11 now
  338. contains the QuickFind indexing system that should fit your needs.  See 
  339. "Reading C=Hacking" (Reference: rch) for information on how to utilize the 
  340. indexing system.  We would like to add that C=Hacking appreciates your 
  341. personal thanks.
  342.  
  343. #(A)c: Are We Talking the Same Language?
  344. From: Jack Vander White <ceejack@crl.com>
  345.  
  346. Dear C=Hacking,
  347. Noticed something that may be a potential problem and thought I would 
  348. let you know.
  349.   
  350. Way back when hacking mag started I didn't have Internet access. the first
  351. couple of issues were sent to me by fellows who had downloaded them and in
  352. downloading had set their terms to translate them to PETSCII. This of 
  353. course changed the coding in the uuencoding parts of the magazine and made
  354. them decode improperly. 
  355.  
  356. Since then I have my own access and have re-downloaded them and posted 
  357. them on my BBS in the original straight ASCII so that those who download
  358. them can uudecode the relevant parts and then translate the text for 
  359. reading.
  360.   
  361. Since different Terminal Programs are using different Translation tables
  362. I can see all kinds of problems in this for the average user.
  363.   
  364. Any comment????
  365.   
  366. Jack VW
  367.  
  368. #(A)r:
  369. The HTML version of Commodore Hacking utilizes the ISO-8859-1 text
  370. encoding standard, while the text version utilizes its 7-bit subset, 
  371. commonly called ASCII.  Normally, the encoding standard poses little
  372. problem, as text uses but a nominal set of characters which can be
  373. translated between PETSCII and ASCII.  However, as you point out, the
  374. uucode format uses more characters, which may or may not be
  375. translated correctly.  To circumvent this problem, which only occurs
  376. in the text version, the files embedded in a Commodore Hacking issue 
  377. should be uudecoded prior to converting the file to anoy alternate
  378. format.
  379.  
  380. ============================================================================
  381.  
  382. #(@)news: Newsfront
  383.  
  384. *  Although not new news, Some still may not know that Creative Micro Designs,
  385.    Inc., is currently designing the Super64CPU accelerator.  This external
  386.    3" tall by 6" wide by 2" deep cartridge will allow Commodore computers
  387.    to execute programs at either 10MHz or 20MHz  (actually, 9 and 18 MHz, 
  388.    realistically).  The unit uses the Western Design Center's 65C816S CPU,
  389.    which is object code compatible with the 6502/6510/8502.  The CPU, used
  390.    in the Super Nintendo Entertainment System as well as other products, can
  391.    be switched between 6502 emulation mode and "native" mode, which allows
  392.    the following:
  393.    
  394.    o  access to 16 MB of RAM without bank switching.
  395.    o  64kB stack.
  396.    o  64kB zero page (now called "direct access").
  397.    o  16 bit registers.
  398.    o  Support for virtual memory systems.
  399.  
  400.    The unit is scheduled for production in February, 1996, and will cost 
  401.    ~US$149.00 for the 10MHz unit and US$199.00 for the 20MHz unit.  
  402.  
  403. *  The following information was relayed to the USENET newsgroup comp.sys.cbm
  404.    by Jack Vanderhite, editor and publisher of COMMODORE CEE disk magazine:
  405.    
  406.       Rather than reply to all the messages asking about DIEHARD I will tell
  407.       all what has been happening over the last few days. 
  408.  
  409.       Brian Crosthwaite, Publisher of Diehard, contacted CMD, Loadstar, and
  410.       Commodore CEE this week with the following form letter faxed to each of
  411.       us:
  412.       -----------
  413.       
  414.       Diehard, the Flyer for commodore 8bitters is planning to cease 
  415.       publication and we are looking to transfer our subscription fulfillment.
  416.       Our number of outstanding subscribers is approximately 8,400 and I 
  417.       would be willing to throw in the balance of the list, totaling 
  418.       approximately 12,000.
  419.          
  420.       Please call me at (xxx)xxx-xxxx if you are interested in acquiring these
  421.       readers and names.
  422.       
  423.       Sincerely, 
  424.       
  425.       Brian L. Crosthwaite
  426.       Publisher
  427.       
  428.       ----------
  429.       
  430.       Each of us did contact Brian for further details. They are bleak. The
  431.       total number of paper issues due to subscribers is approximately 64,000.
  432.       This does not count the approximately 1,200 spinner subscribers which
  433.       would make approximately 10,000 disks due. 
  434.       
  435.       The cost of publishing alone would amount to approximately $100,000 for
  436.       printing, layout, disks, ,mail cost, etc. Not taking into account the
  437.       cost of articles, etc.
  438.       
  439.       when asked about money Brian's only comment was "There is none. It's 
  440.       gone."
  441.  
  442.       a further complication is that Tom Netsel told me last week that General
  443.       Media says that Brian has assumed the obligation to deliver the balance
  444.       of the Gazette subscriptions. I questioned Brian about this. Brian says 
  445.       that general media faxed him the terms of transference of the 
  446.       obligation and that he faxed back an acceptance of the terms.  While I 
  447.       have not seen the actual faxes involved it does sound like offer and 
  448.       acceptance of a binding contract from here.
  449.       
  450.       Obviously, all of us have rejected this offer. I have been told that 
  451.       there is an issue of Diehard at the printers, probably printed. 
  452.       However, the printing bill alone is over $8,000 plus the cost 
  453.       of mailing. Since there is no money it sits there.   
  454.       
  455.       If anyone were willing to assume the total obligations they would have 
  456.       to assume a liability of well over $100,000 over the next year before 
  457.       any returns from renewals would even make a dent in this huge 
  458.       obligation.
  459.       
  460.       Please Note: I am putting this out as a public message. This is ALL I 
  461.       know.
  462.  
  463.       Please do not come back at me asking questions. I have nothing more I can
  464.       add to this.   
  465.       
  466.       Jack VW
  467.     
  468.    So, if you have outstanding issues of dieHard due you, as the editor 
  469.    does,  the fears have been confirmed.  However, for those who purchased 
  470.    the dieHard "Spinner" disk, read on for the encouraging news.
  471.  
  472. *  The LOADSTAR disk magazine has been recently purchased from Softdisk 
  473.    Publishing by LOADSTAR principles Fender Tucker and Julie Mangham.  Now 
  474.    owned by J and F Publishing, a corporation founded by Mr. Tucker and Mrs.
  475.    Mangham, provide the magazine with even more flexibility   Tucker 
  476.    states that now LOADSTAR is "more solvent then ever before".  Existing 
  477.    subscribers will see no difference with this change, as Softdisk and 
  478.    LOADSTAR will continue to maintain a close relationship, with Softdisk 
  479.    continuing to handle subscriptions, in addition to other tasks.  
  480.    
  481.    In related news, J and F Publishing has agreed to fulfill the remainder 
  482.    of the outstading dieHard "Spinner" subscriptions.  Although 
  483.    unfortunate that dieHard left its subscribers out in the cold, it 
  484.    is commendable that these subscriptions will be fulfilled with 
  485.    LOADSTAR issues.  The agreement will provide one issue of LOADSTAR 
  486.    for every two issues of the Spinner, as the Spinner was a single 
  487.    disk, whereas LOADSTAR is double that.  No word has been heard yet on 
  488.    the fate of dieHard paper subscriptions.  All 1200 Spinner 
  489.    subscribers should be receiving information about the 
  490.    subscription fulfillment soon.
  491.  
  492. *  For those people wishing to use the Internet with their Commodore 64, 
  493.    only to find out that the local Internet Service Provider (ISP) only 
  494.    provides Serial Line Internet Protocol (SLIP) service with no shell 
  495.    account service, help is coming.  A prototype Transmissions Control 
  496.    Protocol/Internet Protocol (TCP/IP) protocol stack with SLIP support has 
  497.    been developed by Daniel Dallmann 
  498.    (Daniel.Dallmann@studbox.rus.uni-stuttgart.de) of Germany.  Available now 
  499.    via the Internet (ftp://131.188.190.131:/pub/c64), the package is by no 
  500.    means complete, but does include the basic TCP/IP stack, the SLIP driver, 
  501.    and a rudimentary Telnet application.  
  502.    
  503. *  Another Commodore hardware/software supplier has announced its online
  504.    presence: Performance Peripherals Incorporated.  Maker of the RAMDrive
  505.    and BB units (BBGRAM, BBRTC, and BBGRam), PPI published an online catalog 
  506.    that users can retrieve via the C=Hacking WWW Site 
  507.    (http://www.msen.com/~brain/pub/PPI_catalog.11.95.txt) and the 
  508.    C=Hacking MAILSERV server. (send PPI_catalog.11.95.txt).  In addition to
  509.    importing FLASH8 (the 8MHz accelerator cartridge from Germany), PPI 
  510.    manufactures CommPort, which is a 6551 UART cartridge (ala Swiftlink) 
  511.    which has the basic 6551 functionality with the addition of switch 
  512.    selectable NMI or IRQ interrupt triggering and switch-selectable 
  513.    $de00/$df00 addressing.  
  514.  
  515. *  PPI has one more trick up its sleeve.  PPI will be carrying Novaterm 9.6,
  516.    the newest version of Nick Rossi's oft-used terminal program for the 
  517.    C64.  The blurb follows:
  518.  
  519.       Novaterm 9.6 is a complete terminal emulation program on cartridge for 
  520.       the C64. Novaterm has several features such as 80 column ANSI on a stock 
  521.       C64, and compatibility with CommPort, RAMDrive, BBGRam, and many other 
  522.       hardware devices. Just connect a BBGRam, and Novaterm can use it as a
  523.       "buffer" for storing text or as a "virtual disk" for quickly and easily
  524.       downloading files. Definately the perfect setup for Internet usage. And 
  525.       since Novaterm is in cartridge form, the program loads in seconds, not 
  526.       minutes. Novaterm 9.6 is the latest version programmed by NICK ROSSI. 
  527.       Includes autoboot switch.
  528.  
  529. ============================================================================
  530.  
  531. #(@)trick: Hi Tech Trickery: Sample Dither 
  532.            by George Taylor (yurik@io.org)
  533.  
  534. #(A): Introduction
  535.  
  536. You may know of dithering in graphics.  It is when a limited number of
  537. colors are used to simulate more.  This is done by randomly arranging the
  538. pixels so they blend at a distance, creating an average of the shades.
  539. Here, screen space is being averaged, and more shades are being produced.
  540. In playing samples, time is being averaged, and more bits are being produced.
  541.  
  542. #(A): Dithering Sound
  543.  
  544. Let's say we do the following:
  545.  
  546.                 lda #8
  547.                 sta $d418       This code toggles the low bit of the output.
  548.                 lda #9
  549.                 sta $d418
  550.  
  551. Over an average of time, this is the same as:
  552.  
  553.                 lda #8.5        But we can't really do this.
  554.                 sta $d418
  555.  
  556. This idea can be used to easily do 5 bit sound.  Basically, we take a
  557. 5 bit sample, shift right, then add 0.  If bit 0 was high,
  558. it will increment the 4 bit number.  Then as this adding takes place,
  559. toggling bit 0, it will average out to give half a bit.
  560.  
  561. #(A): Is There a Catch?
  562.  
  563. There is one drawback though.  This toggling can be heard as the high
  564. frequency square wave it resembles.  You must use a high enough sample
  565. rate so this can't be heard.  Also it takes two bit toggles to create the
  566. 5th bit, so you must double the sample rate.  In order to play 8.5, for
  567. example, you must play 8 and then 9, so the 8 and 9 must take half the normal
  568. time, or your sample will play too slow.
  569. One other problem is that there is the possibility of overflow.  In this
  570. case you can use hard clipping on the signal.  In other words, the 5 bit
  571. sample 31 will be played at 16, so instead play 15.
  572.  
  573. This is actually called pulse width modulation.  It is a good example for
  574. illustrating sample dithering.  For example, you can play TRUE 16 bit sound,
  575. even with one bit. To do this, take the 16 bit sample, add a 12 bit random
  576. number, then play the high 4 bits of this result.  Also remember the clipping
  577. problem as mentioned above.
  578.  
  579. @(A): How Is This Like Pulse Width Modulation?
  580.  
  581. The random number range is proportional to the 16 bit sample.  If the 16 bit
  582. number is high, then it is very likely the 0 bit (toggle bit) is high.  It is
  583. the random number which allows the toggle bit to change.  So now we have 16
  584. bit sound with 16db signal to noise ratio.
  585.  
  586. There are some more advanced technical issues to this.  The kind of random
  587. number you choose affects the results.  You need a triangle density function
  588. for perfect linearity (ie., for no distortion).  This is the relationship
  589. of random numbers in the sequence, and does not affect the probability
  590. distribution, which should be equal.  The choice of density function is a
  591. tradeoff between added noise and linearity.  I used pulse density function
  592. in my demo, which is non-filtered random numbers, and it's ok but I can
  593. still hear some noise pumping.
  594.  
  595. #(A): Conclusion
  596.  
  597. Enjoy the ditherdigi!
  598.  
  599. #(A)5bit: Listing One:  5 bit play routine
  600.  
  601. Memory map:
  602. 3:     start page of sample
  603. 4:     end page of sample
  604. 5:     sample period (remmber to play twice normal speed)
  605. fb,fc: pointer to sample
  606.  
  607. start lda 3
  608.       sta $fc
  609.       lda #0
  610.       sta $fb           ; initialize sample pointer
  611.       lda #$b
  612.       sta $d011         ; blank screen for better timing
  613.       sei               ; disable interrupts for better timing
  614. play  lda ($fb),y
  615.       lsr
  616.       sta $d418         ; push sample
  617.       ldx 5
  618. d     dex
  619.       bne d
  620.       pha
  621.       nop
  622.       adc #0
  623.       cmp #$10
  624.       beq s1
  625.       sta $d418
  626.       bpl s
  627. s1    nop
  628.       nop
  629.       nop
  630. s     pla
  631.       ldx 5
  632. d1    dex
  633.       bne d1
  634.       iny
  635.       bne play
  636.       inc fc
  637.       lda fc
  638.       cmp 4
  639.       bne play
  640.       lda #$1b
  641.       sta $d011
  642.       cli
  643. end   rts
  644.  
  645. #(A): References
  646.  
  647. Consult the proceedings of the ACM for further info on digi dithering.
  648.  
  649. ============================================================================
  650.  
  651. #(@)mags: Hacking the Mags
  652.  
  653. Not everything good and/or technical comes from Commodore Hacking, which is
  654. as it should be.  (I still think we have the most, though...)  Thus, let's
  655. spotlight some good and/or technical reading from the other Commodore 
  656. publications.
  657.  
  658. If you know of a magazine that you would like to see summarized here, let 
  659. C=Hacking know about it.  These summaries are only limited by Commodore 
  660. Hacking's inability to purchase subscriptions to all the Commodore 
  661. publications available.  We are very grateful to those publications that send
  662. complimentary copies of their publications for review.
  663.  
  664. #(A): COMMODORE CEE
  665.    Volume 1, Issues 1 and 2 came all packaged as one "mega-issue". This
  666.    particular double issue should be renamed the memory map issue, with 
  667.    I/O and/or memory maps for the VIC, 64, 128, and PET computers.  
  668.    Information on 6522 bugs and on the 6526 CIA chips that was cut from the 
  669.    final compilation of the Commodore 64 Prorammer's Reference Guide is
  670.    of interest to Commodore Haking readers.  Some of the information is
  671.    culled from the Internet: the 64 memory maps, the info on the 6522, and a 
  672.    list of all the CSG produced IC numbers with descriptions.  Of course, these
  673.    files are also available on the Internet, if you have access.  Howver, for 
  674.    those who don't know where to look or for those without access, the 
  675.    information is welcome. Issue 3 has a PCX to GEOPaint converter, much like
  676.    _LOADSTAR_, and Issue 4 will begin a column on PAL to NTSC program 
  677.    conversions.  One thing we'd like to see at Commodore Hacking is a better
  678.    menu program, as the current one is somewhat hard to navigate.
  679.  
  680. #(A): Commodore World
  681.    Issue 10 just arrived at the computer room, with a snazzy front cover.  
  682.    Slick paper aside, the picture of Al Anger's Tower 128 was a masterpiece. 
  683.    Editor Doug Cotton spews about the hype of Windows 95, and the first ads 
  684.    for the Super 64 CPU accelerator are present.  If you're into hardware 
  685.    mods, you can't miss page 4, which shows some other Al Anger hacked 
  686.    Commodore creations.  Jim Butterfield's 4 page 65XX ML reference is 
  687.    useful for the newer programmers, and Doug Cotton's Assembly Line topic of 
  688.    serial routines will help those disk I/O challenged in the crowd.  This 
  689.    issue details the high level routines, while #11 will tackle the low level 
  690.    disk I/O.  Maurice Randall goes over event handling in GEOS, while Al Anger
  691.    details how to disable the internal 1571D in the C128D.  Gaelyne Moranec
  692.    touches on the Internet nitty-gritty of learning UNIX commands and 
  693.    includes a table of UNIX-like commands found in ACE and LUnix.  At the end,
  694.    though, C=Hacking's burning question is:  What hangup does Doug have with 
  695.    those abstract graphics sprinkled throughout the mag?  There's nothing 
  696.    wrong with them, but some look like those psycho-analyst inkblot test 
  697.    cards.   
  698.  
  699. #(A): Driven
  700.    Driven 9 contains a rundown on USENET (written by Jim Brain), which will
  701.    help those Internet "newbies".  For those doing cross development, the
  702.    review of the PC<->C64/C128 networking system called 64NET by Paul Gardner-
  703.    Stephen might help some get object code from the PC to the 64/128.  Eddie
  704.    Bourdon has some info on GEnie, including what Commodore support is
  705.    available.  
  706.  
  707.    Driven 10 presents some useful WWW addresses, while XMikeX and Pegasus
  708.    tackle the issues of apathy and pessimism in the Commodore community.  Both
  709.    make for good reading, but the best (in our opinion) was the pessimism
  710.    piece.  How many times have YOU been laughed out of CompUSA for mentioning
  711.    that modem or SCSI drive was for a Commodore?
  712.  
  713. #(A): LOADSTAR
  714.    Issue 138 just finished loading on the 1581 disk drive, and the disk is
  715.    packed with information.  Fender Tucker goes into much detail on the
  716.    recent changes at LOADSTAR and its new Publishing company, J and F
  717.    Publishing.  Of interest to programmers is the PCX to GEOPaint converter
  718.    program, written by Fender Tucker and Doreen Horne.  Some details on Al
  719.    Angers machines that are shown in Commodore World are related.  Jeff Jones
  720.    presents a simple program pause routine, which fiddles with the NMI 
  721.    interrupt, and gives out source code as well.  The Internet 101 series takes
  722.    a month off from the LOADSTAR letter in #28, but is expected back next
  723.    month.  Lastly, Dave Moorman presents his fractal generator called FRACTAL
  724.    MOUNTAINS.  C=Hacking couldn't get it to work, but we think it's user error.
  725.  
  726. #(A): LOADSTAR 128
  727.    In Issue 29, Fender apologizes for not paying enough attention to the 800
  728.    LOADSTAR 128 subscribers.  Of interest to programmers is the program listing
  729.    pause program on the issue, but the rest is pretty light stuff, not to knock
  730.    LOADSTAR.  Different audiences need different material.
  731.  
  732. #(A): Vision
  733.    
  734.    In Issue 7, Rick Mosdell has an article on graphics formats, updated and
  735.    reproduced in this issue (Reference: gfx).  There is some information from
  736.    USENET reproduced, and a list of FTP sites as posted to USENET is
  737.    also presented.  Not much technical content in here, but C=Hacking was
  738.    impressed with the graphics, music, and stories in the mag.  Besides, 
  739.    everyone needs some time to enjoy the machine. 
  740.  
  741. Other magazines not covered in this rundown include _The Underground_, 
  742. _Gatekeeper_, _Commodore Network_, _64'er_, _Atta Bitar_ (_8 bitter_), as well
  743. as those C=Hacking is simply not aware of.  As soon as we can snag a copy of 
  744. any of these, or get the foreign language ones in English :-), we will give 
  745. you the scoop on them.  
  746.  
  747. ============================================================================
  748.  
  749. #(@)dbldma: Speed up RAMLink transfers with the Double-DMA Technique 
  750.             by Doug Cotton (cmd-doug@genie.com) and Mark Fellows 
  751.  
  752. #(A): Introduction
  753.  
  754. When CMD designed the RAMLink, we tried to make the system as fast as possible,
  755. but costs and complexity prohibited us from duplicating the operation of the 
  756. DMA operation found in the Commodore RAM Expansion Unit (REU),  The 8726 DMA
  757. controller found in the REU is a very complex item that allows the REU to
  758. transfer one byte per 1 MHz CPU clock cycle (1 microsecond).  On the other 
  759. hand, the RAMLink uses the 6510/8502 CPU load and store operations to transfer
  760. memory from the RAMLink memory to main memory.  For the user who uses RL-DOS
  761. and RAMDOS, the difference is not noticeable, because although the RAMLink
  762. transfer is slower, RAMDOS continually pages its code in and out of main 
  763. memory, effectively slowing its effective transfer speed down significantly.  
  764.  
  765. But, what if the programmer isn't using RAMDOS?  Then, the speed of the RAMLink
  766. becomes an issue.  The RAMLink takes about 8 cycles to perform a transfer
  767. of a byte, while the REU does it in 1.  This is significant.  However, if a
  768. user owns both a RAMLink and an REU, there is a way to boost the transfer rate
  769. of the RAMLink via software.  The method is called Double-DMA.  
  770.  
  771. #(A): Double-DMA Description
  772.  
  773. Basically, the process is quite simple.  Since the REU has the ability to
  774. transfe memory at 1 byte/microsecond, you can use the REU DMA to transfer
  775. memory from the RAMLink to main memory.  To understand how we can do this,
  776. remember that the normal RL-DOS transfer routines use the CPU to perform the
  777. memory transfer.  Well, to do that, at least some of the RAMLink RAM must be
  778. mapped into main memory.  To be exact, 256 bytes is mapped in.  So, to 
  779. utilize the Double-DMA technique, the programmer simply makes the 
  780. appropriate 256 bytes of RAMLink memory to be transferred visible in the 
  781. main memory map, uses the REU to transfer that 256 bytes to the REU, and then
  782. uses the REU to transfer the 256 bytes in the REU to its destination in the
  783. main memory map. Thus, the Double-DMA technique will allow the RAMLink to
  784. transfer data at rouyghly 1/2 the speed of the REU, or 3-4 times faster than
  785. using the CPU to perform transfers.
  786.  
  787. #(A): The RAMLink memory map
  788.  
  789. To achieve this transfer speed gain, the programmer must forego RL-DOS
  790. usage and write specialized transfer routines.  To do that, we need to
  791. discuss how the RAMLink maps itself into main memory and detail the various
  792. RAMLink registers needed to make this feat possible:
  793.  
  794. Address Description
  795. ------- -----------
  796. $de00   256 bytes of data (See $dfc0-$dfc3 for more information)
  797. $df7e   write to this location to activate the RAMLink hardware
  798. $df7f   write to this location to deactivate the RAMLink hardware.
  799. $dfa0   lo byte of requested RAMCard memory page
  800. $dfa1   hi byte of requested RAMCard memory page
  801. $dfc0   write to this location to show RL variable RAM at $de00 (default)
  802. $dfc1   write to this location to show RAMCard memory at $de00
  803. $dfc2   write to this location to show the RAM Port device $de00 page at $de00
  804. $dfc0   write to this location to show Pass-Thru Port dev. $de00 page at $de00
  805.  
  806.  
  807. For all locations that have the description "write to this address...", the
  808. program can safely write any byte to those locations, as the RAMLink hardware
  809. simply waits for an access, not any particular byte to be written.
  810.  
  811. #(A): Order of Operations
  812.  
  813. Although the Double-DMA technique relies on use of the REU, it is beyond the
  814. scope of this article to detail how to access the REU RAM under programmatic
  815. control.  For more information on transferring data from the Commodore 128/64
  816. and the 17XX REU, refer to the back of a REU owner's manual.  
  817.  
  818. The following steps will realize the Double-DMA method:
  819.  
  820. Notes:  P = PAGE in RAMCard RAM to be transferred to/from
  821.         A = PAGE of RAM in main memory to be transferred to/from
  822.         X = single page of memory in REU used as temp RAM
  823.  
  824.  
  825.  1)  if computer = 128, set up correct RAM bank
  826.  2)  make I/O visible in main memory
  827.  3)  sei
  828.  4)  sta $df7e - activate RAMLink
  829.  5)  lda #<P
  830.  6)  sta $dfa0
  831.  7)  lda #>P
  832.  8)  sta $dfa1
  833.  9)  sta $dfc1 - make $de00 show PAGE of RAM on RAMCard
  834.  
  835. Now, with the RAMLink hardware enabled in this way, the REU registers are
  836. also visible, so one can do a double DMA transfer at this point.  There
  837. are two choices:
  838.  
  839. Transfer A->P:
  840.  
  841. 10)  set up REU for A->X transfer
  842. 11)  initiate REU DMA transfer
  843. 12)  set up REU for X->$de00 transfer
  844. 13)  initiate REU DMA transfer
  845.  
  846. Transfer P->A
  847.  
  848. 10)  set up REU for X->$de00 transfer
  849. 11)  initiate REU DMA transfer
  850. 12)  set up REU for A->X transfer
  851. 13)  initiate REU DMA transfer
  852.  
  853. Now, to go on:
  854.  
  855. 14)  If more byte need transferrring, A=A+1, P=P+1, goto 5
  856. 15)  sta $dfc1 - restore contents of $de00
  857. 15)  sta $df7f - deactivate RAMLink hardware
  858. 16)  if computer = 128, restore bank
  859. 17)  restore I/O visibility if needed
  860. 18)  cli
  861.  
  862. #(A): Address Translation
  863.  
  864. To effectively use the Double-DMA technique, a programmer will want to
  865. set up a DACC partition in the RAMLink for use as external RAM.  The
  866. programmer will need to determine the start address of the partition with the
  867. RL-DOS G-P command (or its sister command, G-[shift]P)  This command will
  868. return the address of the DACC partition, or will it?
  869.  
  870. The answer is: Maybe.  If a user has inserted an REU into the RAMLink RAM
  871. port and has the Normal/Direct swittch set to Normal, RL-DOS uses REU memory 
  872. as the lowest RAM in the RAMLink memory map. However, when directly accessing 
  873. the RAMLink and bypassing RL-DOS, the REU is not mapped into the RAMLink 
  874. memory map. So, for such a condition, the code that determines the start of 
  875. the DACC partition must SUBTRACT the size of the REU from the address returned
  876. by the G-P command.  It's non-utopian, but the program need only do this once.
  877. However, for such an REU configuration, one must take care to ensure that at 
  878. least 256 bytes of REU RAM is available and not already in use before 
  879. utilizing the Double-DMA technique.
  880.  
  881. #(A): Performance
  882.  
  883. Craig Bruce, who has implemented this technique in his ACE operating system,
  884. provides the following performance figures for different access techniques:
  885.  
  886. Type            Bandwidth   Latency Notes
  887.                 (bytes/sec) (~usec)
  888. -------------   ---------   ------- -----
  889. REU             1,007,641      65.8 REU in Direct mode
  890. REU thru RL     1,007,641      77.8 REU in RAM Port in Normal mode
  891. RAMLink           105,792     199.2 Regular RAMLink access
  892. RL with REU       372,827     319.8 Double-DMA
  893. Internal RAM0     120,181      44.2 Zero-page
  894. Internal RAM1      80,283      56.3 All main memory except zero-page
  895.  
  896. So, using this technique in ACE results in a 3.7x increase in transfer speed.
  897. For some applications, that is well worth the trouble.
  898.  
  899. #(A): Conclusion
  900.  
  901. Obviously, CMD recommends that the RL-DOS be used for most operations, but
  902. we realize that some programmers simply need faster transfer rates.  The
  903. Double-DMA technique should provide the speed needed from the RAMLink. 
  904. Obviously, since this technique bypasses RL-DOS, code using it can
  905. potentially corrupt RAMLink memory if errors occur or if the technique is
  906. improperly used. When using the technique, we recommend extensive testing
  907. using various DACC partitions and different REU configurations to ensure
  908. proper operation.  
  909.  
  910. #(A)ddcode: Double-DMA Code
  911.  
  912. Following is a set of functions that will perform transfers using Double-DMA.
  913. They are copied from the routines used in Craig Bruce's ACE operating system,
  914. Release 14, which incorporates the Double-DMA method.  We thank Craig for
  915. the code below:
  916.  
  917. ; Name:        Double-DMA memory transfer
  918. ; Author:      Craig Bruce
  919. ; Date:        1995-12-4
  920. ; Description: The following routines use the Double-DMA technique to transfer
  921. ;              memory to/from main RAM and the RAMLink.  If no RL is present,
  922. ;              normal CPU transfer methods are utilized.
  923. ;
  924. ; Variables:   [mp] holds the address of RAMCard memory to transfer
  925. ;              ramlinkNearPtr hold the address of main memory to transfer
  926. ;              ramlinkLength is length of data to transfer
  927. ;              ramlinkOpcode = $90: main memory -> RL
  928. ;                            = $91: RL -> main memory 
  929.  
  930. reu = $df00
  931. rlActivate   = $df7e
  932. rlDeactivate = $df7f
  933. rlSram       = $dfc0
  934. rlPageSelect = $dfa0
  935. rlPageActivate = $dfc1
  936. rlPageData   = $de00
  937.  
  938. ramlinkOpcode .buf 1
  939. ramlinkLength .buf 2
  940. ramlinkNearPtr .buf 2
  941. ramlinkMpSave .buf 3
  942. ramlinkZpSave .buf 2
  943.  
  944. ramlinkOp = *  ;( [mp]=farPtr, ramlinkNearPtr, ramlinkLength, ramlinkOpcode )
  945.    lda mp+0
  946.    ldy mp+1
  947.    ldx mp+2
  948.    sta ramlinkMpSave+0
  949.    sty ramlinkMpSave+1
  950.    stx ramlinkMpSave+2
  951.    lda zp+0
  952.    ldy zp+1
  953.    sta ramlinkZpSave+0
  954.    sty ramlinkZpSave+1
  955.    lda ramlinkNearPtr+0
  956.    ldy ramlinkNearPtr+1
  957.    sta zp+0
  958.    sty zp+1
  959.    clc
  960.    lda mp+1
  961.    adc aceRamlinkStart+0
  962.    sta mp+1
  963.    lda mp+2
  964.    adc aceRamlinkStart+1
  965.    sta mp+2
  966. -  lda ramlinkLength+0
  967.    ora ramlinkLength+1
  968.    beq +
  969.    jsr rlTransferChunk
  970.    jmp -
  971. +  lda ramlinkMpSave+0
  972.    ldy ramlinkMpSave+1
  973.    ldx ramlinkMpSave+2
  974.    sta mp+0
  975.    sty mp+1
  976.    stx mp+2
  977.    lda ramlinkZpSave+0
  978.    ldy ramlinkZpSave+1
  979.    sta zp+0
  980.    sty zp+1
  981.    clc
  982.    rts
  983.  
  984.    rlTrSize .buf 1
  985.  
  986.    rlTransferChunk = *  ;( [mp]=rlmem, (zp)=nearmem, rlLength, rlOpcode )
  987.    ;** figure maximum page operation
  988.    lda ramlinkLength+1
  989.    beq +
  990.    lda #0
  991.    ldx mp+0
  992.    beq rlTrDo
  993.    sec
  994.    sbc mp+0
  995.    jmp rlTrDo
  996. +  lda mp+0
  997.    beq +
  998.    lda #0
  999.    sec
  1000.    sbc mp+0
  1001.    cmp ramlinkLength+0
  1002.    bcc rlTrDo
  1003. +  lda ramlinkLength+0
  1004.  
  1005.    ;** do the transfer
  1006.    rlTrDo = *
  1007.    tay
  1008.    sty rlTrSize
  1009.    jsr rlPageOp
  1010.  
  1011.    ;** update the pointers and remaining length
  1012.    clc
  1013.    lda rlTrSize
  1014.    bne +
  1015.    inc mp+1
  1016.    inc zp+1
  1017.    dec ramlinkLength+1
  1018.    rts
  1019. +  adc mp+0
  1020.    sta mp+0
  1021.    bcc +
  1022.    inc mp+1
  1023. +  clc
  1024.    lda zp+0
  1025.    adc rlTrSize
  1026.    sta zp+0
  1027.    bcc +
  1028.    inc zp+1
  1029. +  sec
  1030.    lda ramlinkLength+0
  1031.    sbc rlTrSize
  1032.    sta ramlinkLength+0
  1033.    bcs +
  1034.    dec ramlinkLength+1
  1035. +  rts
  1036.  
  1037.    rlPageOp = *  ;( [mp]=rlmem, (zp)=nearmem, .Y=bytes, ramlinkOpcode )
  1038.    php
  1039.    sei
  1040.    sta rlActivate
  1041.    lda mp+1
  1042.    sta rlPageSelect+0
  1043.    lda mp+2
  1044.    sta rlPageSelect+1
  1045.    sta rlPageActivate
  1046.    lda aceReuRlSpeedPage+3
  1047.    bne rlPageOpReu  ;xxx dependency on aceMemNull==0
  1048.    rlPageOpNonReu = *
  1049.    tya
  1050.    clc
  1051.    adc mp+0
  1052.    tax
  1053.  
  1054.    lda ramlinkOpcode
  1055.    cmp #$91
  1056.    bne rlPageOpWrite
  1057.    dex
  1058.    dey
  1059.    beq +
  1060. -  lda rlPageData,x
  1061.    sta (zp),y
  1062.    dex
  1063.    dey
  1064.    bne -
  1065. +  lda rlPageData,x
  1066.    sta (zp),y
  1067.    jmp rlPageOpContinue
  1068.  
  1069.    rlPageOpWrite = *
  1070.    dex
  1071.    dey
  1072.    beq +
  1073. -  lda (zp),y
  1074.    sta rlPageData,x
  1075.    dex
  1076.    dey
  1077.    bne -
  1078. +  lda (zp),y
  1079.    sta rlPageData,x
  1080.  
  1081.    rlPageOpContinue = *
  1082.    sta rlSram
  1083.    sta rlDeactivate
  1084.    plp
  1085.    rts
  1086.  
  1087.    rlPageOpReu = * ;( [mp]=rlmem, (zp)=nearmem, .Y=bytes, ramlinkOpcode )
  1088.    ;** ramlink hardware already switched in
  1089.    ldx #1
  1090.    tya
  1091.    beq +
  1092.    ldx #0
  1093.    cmp #0  ;xx cut-off value
  1094.    bcc rlPageOpNonReu
  1095. +  ldy ramlinkOpcode
  1096.    cpy #$90
  1097.    beq +
  1098.    ldy #$90            ;rl->reu->intern
  1099.    jsr rlPageOpReuRl
  1100.    ldy #$91
  1101.    jsr rlPageOpReuIntern
  1102.    jmp ++
  1103. +  ldy #$90            ;intern->reu->rl
  1104.    jsr rlPageOpReuIntern
  1105.    ldy #$91
  1106.    jsr rlPageOpReuRl
  1107. +  sta rlSram
  1108.    sta rlDeactivate
  1109.    plp
  1110.    rts
  1111.  
  1112.    rlPageOpReuIntern = *  ;( .AX=bytes, .Y=op )
  1113.    sta reu+7  ;len
  1114.    stx reu+8
  1115.    sty temp1
  1116.    pha
  1117.    lda zp+0
  1118.    ldy zp+1
  1119.    sta reu+2
  1120.    sty reu+3
  1121.    lda aceReuRlSpeedPage+0
  1122.    ldy aceReuRlSpeedPage+1
  1123.    sta reu+4
  1124.    sty reu+5
  1125.    lda aceReuRlSpeedPage+2
  1126.    sta reu+6
  1127. .if computer-64
  1128.    ldy vic+$30
  1129.    lda #0
  1130.    sta vic+$30
  1131. .ife
  1132.    lda temp1
  1133.    sta reu+1
  1134. .if computer-64
  1135.    sty vic+$30
  1136. .ife
  1137.    pla
  1138.    rts
  1139.  
  1140.    rlPageOpReuRl = *  ;( .AX=bytes, .Y=op )
  1141.    sta reu+7  ;len
  1142.    stx reu+8
  1143.    sty temp1
  1144.    pha
  1145.    lda mp+0
  1146.    ldy #>rlPageData
  1147.    sta reu+2
  1148.    sty reu+3
  1149.    lda aceReuRlSpeedPage+0
  1150.    ldy aceReuRlSpeedPage+1
  1151.    sta reu+4
  1152.    sty reu+5
  1153.    lda aceReuRlSpeedPage+2
  1154.    sta reu+6
  1155. .if computer-64
  1156.    ldy vic+$30
  1157.    lda #0
  1158.    sta vic+$30
  1159. .ife
  1160.    lda temp1
  1161.    sta reu+1
  1162. .if computer-64
  1163.    sty vic+$30
  1164. .ife
  1165.    pla
  1166.    rts
  1167.  
  1168. ============================================================================
  1169.  
  1170. #(@)usenet: UseNuggets
  1171.  
  1172. COMP.SYS.CBM:  The breeding ground of programmers and users alike.  Let's
  1173. see what topics are showing up this month:
  1174.  
  1175. #(A): We Want More Power!
  1176.    CMD's announcement of the Super64 CPU accelerator got things stirred up
  1177.    in the newsgroup.  When it was announced that the initial product would run
  1178.    on a C64 or on a C128 in 64 mode only, some angry C128 128 mode users
  1179.    vented all over the place.  Everything from people wondering aloud what
  1180.    extra work the 128 version would require to threats of non-purchase of
  1181.    the unit ensued.  Then, just as the first wave of fighting subsided, the
  1182.    next wave started, programmers worried about RAM transfer speed bottlenecks
  1183.    questioned CMD's decision not to include a DMA device on the unit to
  1184.    speed data transfers.  CMD's response:
  1185.  
  1186.       From: Doug Cotton <cmd-doug@genie.geis.com>
  1187.       Newsgroups: comp.sys.cbm
  1188.       Subject: Re: Power Users!
  1189.       Date: 28 Nov 1995 00:59:26 GMT
  1190.       Organization: Creative Micro Designs, Inc.
  1191.       
  1192.       There were some earlier questions about how fast memory transfers 
  1193.       could be accomplished with the accelerator, and at least one 
  1194.       individual emailed me over the lack of a DMA controller. I obtained 
  1195.       some figures from Mark concerning this. Presently, the DMA transfers
  1196.       using an REU transfers a byte in 1 microsecond. The accelerator can 
  1197.       achieve this same speed when transferring data from either 
  1198.       on-board static RAM, or from expansion memory (slower DRAM) to the 
  1199.       host computer RAM. Transfers internally (from static RAM to static 
  1200.       RAM) will take .35 microseconds per byte (350 nanoseconds). 
  1201.       Transfers from RAMLink RAMCard RAM (direct style) to the host 
  1202.       computer RAM will take about 2 microseconds per byte. The only figures 
  1203.       I don't have yet are for transfers between on-board static RAM 
  1204.       and expansion DRAM, but this will be governed by the speed of the 
  1205.       DRAM itself, and the number of wait-states required. It definately 
  1206.       will be faster than 1 byte per microsecond though. So the only 
  1207.       thing slower than a current DMA operation is transferring to and 
  1208.       from RAMLink RAMCard memory, which is still pretty impressive at 
  1209.       half the speed of present DMA transfers.   
  1210.       
  1211.       Given these speeds, the cost of high-speed DMA controllers ($$$$), and 
  1212.       a real lack of anywhere to put one on the main board, I think 
  1213.       going without a DMA controller is reasonable. If you really want 
  1214.       one, though, there's always the high-speed expansion port, and 
  1215.       a do-it-yourself project.
  1216.       
  1217.       Doug Cotton
  1218.       
  1219.    Notice the tiny "high speed expansion port" mention at the end.  Reports
  1220.    indicate that such a port or ports will definitely appear on the unit,
  1221.    but it is still undetermined whether a single connector or a small 
  1222.    expansion bus will be utilized.  Commodore Hacking recommends the latter,
  1223.    as more options for hardware mods are available.
  1224.  
  1225. #(A): Let's all design the Commodore 64 Laptop!
  1226.  
  1227.    Yes, the dreamers are at it once again.  Starting in late October, the
  1228.    net was abuzz with thoughts on what should be included on a Commodore
  1229.    Laptop. The designs were flying fast and furious, with many different
  1230.    features discussed.  It was agreed that the laptop would need to be
  1231.    a power sipper and have an LCD screen and a keyboard.  However, that
  1232.    was where agreement ended.  Some of following items were bantered about:
  1233.  
  1234.    CPU:
  1235.  
  1236.    o  "really fast" 6510
  1237.    o  65C816S
  1238.  
  1239.    Disk:
  1240.  
  1241.    o  FLASH RAM cards.
  1242.    o  built in hard drive
  1243.    o  low power 1581 or CMD FD2000/4000
  1244.    
  1245.    RAM
  1246.  
  1247.    o  definitely more than 64kB, but disagreement as to how much more.
  1248.    
  1249.    Video
  1250.  
  1251.    o  VIC-II compatibility with more modes.
  1252.    o  VIC-III as found in Commodore 65
  1253.  
  1254.    Sound
  1255.  
  1256.    o  Built in stereo SIDs
  1257.    o  Quad SIDs
  1258.  
  1259.    So, on and on it went.  Some got down to the nitty gritty of planning
  1260.    designs for chips.  Some wanted to put the SIDs into one chip, while 
  1261.    others wanted a SID/VIC/CPU single chip solution.  
  1262.  
  1263.    It's December, and the thread is still going strong, but a few great
  1264.    things have surfaced, which is why you can't just discount this type of
  1265.    dreaming:
  1266.  
  1267.    o  Someone posted the procedure for modifying the C64 to run on
  1268.       battery power.
  1269.  
  1270.    o  A few people started looking into how much money such designing would
  1271.       require.
  1272.  
  1273.    o  Most people who thought disk media should be included agreed that the 
  1274.       CMD FD drive could/should be used.  
  1275.  
  1276.    o  Everyone woke up and noticed that the NMOS CPU process used for the
  1277.       fabbibng of the CBM chips was power hungry and ill-suited to battery
  1278.       operation.
  1279.  
  1280.    C=Hacking encourages users to answer the quetion: My dream Commodore
  1281.    laptop computer would include....  Send you entries to Commodore
  1282.    Hacking (brain@mail.msen.com) with the subject "LAPTOP".  We'll print
  1283.    the best entries next issue.
  1284.  
  1285.    Everyone seems to think that CMD is going to have one in development 
  1286.    before long.  Dunno.  Commodore Hacking has heard rumors of what is going
  1287.    on at CMD, but we haven't heard about the laptop project.  Of course, 
  1288.    we're not SPECIAL or anything.... :-)
  1289.  
  1290. #(A): The Tower of Power
  1291.  
  1292.    It seems Al Anger's (coyote@gil.net) Tower 128 picture on Commodore World's
  1293.    Issue 10 cover got everyone excited.  A couple of people were sending Al
  1294.    email about it, Commodore Hacking asked some questions, and some USENETters
  1295.    were deciding how to do it themselves.  Al states that $2000 would just
  1296.    about cover it, which turned a few enquiring minds away, we're sure.
  1297.    Still, the reasons given for wanting a tower were solid.  Commodore users
  1298.    are getting tired of all the clutter and mess cables, power cords,
  1299.    expansion extenders, Swiftlink cartridges, etc. make in the computer room.
  1300.    C=Hacking notes that at least one manufacturer produces tower 64 systems,
  1301.    but the cost is evidently more than what most folks are willing to fork
  1302.    over (~US$300 - US$550).  So, everyone is waiting for the cost to come 
  1303.    down.... 
  1304.  
  1305. #(A): Dave Letterman, Eat Your Heart Out!
  1306.  
  1307.    The latest thread is the top ten list of games.  Everyone is submitting
  1308.    their 10 most favorite games for the CBM machines.  (Is anyone compiling
  1309.    these?)  Anyway, it turns out this thread has a nice side effect.  People
  1310.    are reminiscing about the old games, and the Commodore users are noting
  1311.    that the new games "just aren't as good".  Here, here!
  1312.  
  1313. So, that wraps up the USENET this time.  We try to keep an eye out for 
  1314. stuff of interest, but drop us a line if you think we might miss an IMPORTANT
  1315. topic...
  1316.  
  1317. ============================================================================
  1318.  
  1319. #(@)toolbox: The Graphics Toolbox: Ellipses
  1320.              by Stephen L. Judd (sjudd@nwu.edu)
  1321.  
  1322.  
  1323. #(A): Introduction
  1324.  
  1325. After a much needed break from Commodore 64 programming, I thought it
  1326. would be nice to construct another algorithm for the 2D graphics toolbox.
  1327. Since we did circles last time, a natural successor would be an algorithm
  1328. to draw eclipses.  We will first review the circle algorithm, and then build
  1329. upon it to draw eclipses.  You may recall that the algorithm had problems
  1330. with small-radius circles.  There is a very easy way to fix this, so we will
  1331. cover that issue as well.
  1332.  
  1333. #(A): Circles
  1334.  
  1335.    Recall that the equation for a circle is
  1336.  
  1337.          x^2 + y^2 = r^2
  1338.  
  1339. After taking differentials of both sides, we find that
  1340.  
  1341.          dy = -x/y dx
  1342.  
  1343. That is, if we take a step of size dx in the x-direction, we in principle
  1344. want to take a step of size dy in the y-direction.  
  1345.  
  1346. Next we start at the top of the circle, so that y=r and x=0.  We
  1347. start increasing x in step sizes of one.  We only care about step sizes
  1348. of one, since our basic unit is now a pixel.  The y-coordinate is going to
  1349. start piling up these dy's, and at some point the integer part of y will 
  1350. increase, and we get a new y-coordinate for the pixel.  The idea, then, is to
  1351. keep adding the dy's together, and once their sum is greater than one, we
  1352. decrease y (remember that y starts at the top of the circle).
  1353.  
  1354. The sneaky way to do this is to treat y as an integer "constant".  Then
  1355. it is very easy to add the dy's together, since they have a common denominator
  1356. equal to y. So really all we need to do is start adding x-coordinates together,
  1357. and once their sum is larger than y, we decrease y and hang on to the
  1358. remaining fractional part of dy.  The algorithm then looks like:
  1359.  
  1360.       y=r
  1361.       x=0
  1362.       a=r
  1363. loop: x=x+1
  1364.       a=a-r
  1365.       if a<=0 then a=a+y:y=y-1
  1366.       plot (x,y)
  1367.       if x<y then loop:
  1368.  
  1369. Now, Chris McBride pointed something out to me.  As you may recall,
  1370. the algorithm breaks down for small r.  Chris said that if a is initially
  1371. set to r/2 instead of r, the algorithm works perfectly.  Why is that?
  1372. Recall that we add dy to itself until it is greater than one.  Wouldn't
  1373. it make more sense to add dy to itself until it is greater than 0.5?
  1374. That would have the effect of rounding things up.  Thus, starting at r/2
  1375. is like adding 0.5 to the fractional part of y -- it is the difference
  1376. between INT(y) and INT(y+0.5).
  1377.  
  1378. Thus, the above line
  1379.    
  1380.    a=r
  1381.  
  1382. should be changed to
  1383.  
  1384.    a=r/2
  1385.  
  1386. for a perfect circle every time.  Thus, this corresponds to adding an LSR
  1387. to the machine code.  Incidentally, this fix appeared in an earlier C=Hacking,
  1388. but it was placed in such a crazy place that you probably never saw it.
  1389.  
  1390. #(A): Ellipses, HO!
  1391.  
  1392. Now we can move on to eclipses.  Since ellipses are simply a
  1393. squashed circle, it seems reasonable that we could modify the above circle
  1394. algorithm.  So, let's get to it!
  1395.  
  1396. Everyone knows the equation of an eclipse:
  1397.  
  1398.    x^2/a^2 + y^2/b^2 = 1
  1399.  
  1400. Upon taking differentials of both sides we have,
  1401.  
  1402.    2*x*dx/a^2 + 2*y*dy/b^2 = 0
  1403.  
  1404. or, equivalently,
  1405.  
  1406.    dy = -b^2/a^2 * x/y * dx
  1407.  
  1408. As you can see, life becomes suddenly becomes more complicated by a factor of
  1409. b^2/a^2.  Furthermore, with an eclipse we only have reflection symmetries
  1410. through the x- and y-axis.  In the circle algorithm we could get away with
  1411. just drawing an eighth of the circle, but now we have to draw a full quarter
  1412. of the eclipse.
  1413.  
  1414. We will start drawing the eclipse at x=0, y=b, so that initially x
  1415. will increase by one at each step, and y will wait a few steps to increase.
  1416. At some point, though, we will want y to increase by one at each step, and
  1417. x to wait a few steps before increasing; in the circle algorithm we just quit
  1418. once we reached this point, but now we are going to need an equation for dx:
  1419.  
  1420.    dx = -a^2/b^2 * y/x * dy
  1421.  
  1422. In the circle algorithm, we used a single variable to count up and
  1423. tell us when it was time to increase y.  Perhaps your intuition suggests
  1424. that we can do an eclipse with _two_ variables; mine said the same thing,
  1425. so that is exactly what we will do.
  1426.  
  1427. First, let us assume we have a way of calculating b^2/a^2:
  1428.  
  1429.    E = b^2/a^2
  1430.  
  1431. I will suggest a way to perform this calculation later.  Let's write out
  1432. the first few terms in the dy summation, starting at x=0, y=b:
  1433.  
  1434.    dy1 + dy2 + ... = -E * (x0 + x1 + x2 + x3 + ...)/y
  1435.                    = -E * (0 + 1 + 2 + 3 + ...)/b
  1436.                    = - (0 + E + 2E + 3E + ...)/b
  1437.  
  1438. So, the basic structure of the algorithm is: add up 0, E, 2E, etc. until
  1439. the sum is larger than y.  At that point, reset the counter, keeping the
  1440. remainder, and decrease y.  This is where the two variables come in:
  1441.  
  1442.    X=X+1
  1443.    T2=T2+E
  1444.    T1=T1+T2
  1445.    IF T1>=Y THEN T1=T1-Y:Y=Y-1
  1446.  
  1447. Do you see how it works?  T2 simply takes on the values 0, E, 2E, 3E, etc.,
  1448. and T1 is the counter.  Furthermore, you can see that once T2 is larger
  1449. than Y, dy will be larger than one at each step.  We need a new algorithm
  1450. to continue the calculation, and it turns out to be quite simple.
  1451.  
  1452. Look at the expression for dx above.  We could calculate a^2/b^2,
  1453. but somehow that goes against the spirit of the calculation so far.  Let's
  1454. instead rewrite dx slightly:
  1455.  
  1456.    dx = - y/(E*x) * dy
  1457.  
  1458. Here we have simply written a^2/b^2 as 1/(b^2/a^2) = 1/E.  But E*x is
  1459. exactly the variable T2 above, so we can continue the calcuation without
  1460. even stopping for breath:
  1461.  
  1462.    Y=Y-1
  1463.    T1=T1+Y
  1464.    IF T1>=T2 THEN T1=T1-T2:X=X+1:T2=T2+E
  1465.  
  1466. (remember that T1 keeps track of the fractional part of y).  So, we now
  1467. have a complete algorithm for drawing an eclipse:
  1468.  
  1469.    0 REM ELLIPSE ATTEMPT #N SLJ 11/3/95
  1470.    10 A=150:B=16:E=B*B/(A*A)
  1471.    20 X=0:Y=B:T1=0:T2=0.5
  1472.    30 GRAPHIC1,1:SLOW:X0=160:Y0=100:DRAW1,X0+A,Y0:DRAW1,X0,Y0-B
  1473.    40 X=X+1:T2=T2+E
  1474.    50 T1=T1+T2
  1475.    60 IF T1>=Y THEN T1=T1-Y:Y=Y-1
  1476.    70 DRAW1,X0+X,Y0-Y
  1477.    80 IF T2<Y THEN 40
  1478.    90 Y=Y-1
  1479.    100 T1=T1+Y
  1480.    110 IF T1>=T2 THEN T1=T1-T2:X=X+1:T2=T2+E
  1481.    120 DRAW1,X0+X,Y0-Y
  1482.    130 IF Y>0 THEN 90
  1483.  
  1484. Lines 40-80 are the top part of the eclipse, and lines 90-130 handle the
  1485. bottom part.  Note that T2 starts at 0.5, to round off the calculation in the
  1486. same spirit as we did in the circle algorithm.
  1487.  
  1488. Naturally, this algorithm has a few limitations.  In line 30 the start
  1489. and end points are plotted, so you can see how close the algorithm really is.
  1490. In my experiments it occasionally missed the endpoint by a pixel or two.  As 
  1491. usual, I was a little too lazy to investigate possible ways to get around this.
  1492. If you require a perfect eclipse, you need to start the calculation at x=0, y=b
  1493. and run it forwards (e.g. lines 40-80 above), and then do another, similar
  1494. calcuation, starting at x=a, y=0, and running backwards.  That is, for the
  1495. second calculation, calculate E2=a^2/b^2, and then run the algorithm just like
  1496. lines 40-80, interchanging X and Y.
  1497.  
  1498. Now we need to translate this algorithm into assembly.  I am going
  1499. to make a few assumptions: first, that everything fits in a byte.  In
  1500. particular, I require that b^2/a < 256.  This insures that b^2/a^2 < 256,
  1501. and also insures that T2 will not overflow (note that when x=a, T2=E*a,
  1502. e.g. T2=b^2/a).  What this means is that eclipses can't be too squashed.
  1503.  
  1504. Next, we need to deal with the fraction E=b^2/a^2.  Any number
  1505. like this consists of two parts, an integer part plus a fractional part
  1506. (e.g. a number and a decimal).  So, let's split E into two parts, EL and EH,
  1507. where EL represents the decimal part and EH the integer.  Now our addition
  1508. consists of adding together the fractional parts, and if there is an overflow,
  1509. increasing the integer part.  For example, if E=1.62, then EH=1 and EL=0.62.
  1510. We add EL to our number, and if it is greater than one, we carry the one to
  1511. when we add EH to our number.
  1512.  
  1513. The best thing to do is to represent EL as a fractional part of 256.
  1514. That is, our EL above should really be 0.62*256.  This way, carries and
  1515. overflows will be handled automatically (this will become clear in a moment).
  1516.  
  1517. Let me give some pseudo-assembly code and we'll push off the
  1518. explanation until later:
  1519.  
  1520.    35 GOTO 200
  1521.    190 REM ***********************
  1522.    200 XM=0:YM=B:X=128:Y=0:EH%=INT(E):EL%=INT((E-EH%)*256+0.5)
  1523.    210 XM=XM+1
  1524.    220 C=0:A=X:A=A+EL%:IF A>255 THEN A=A-256:C=1
  1525.    230 X=A:A=Y:A=A+EH%+C:Y=A
  1526.    235 A=A+T1
  1527.    240 IF A>=YM THEN A=A-YM:YM=YM-1
  1528.    250 T1=A:DRAW1, X0+XM, Y0-YM
  1529.    260 IF Y<=YM THEN 210
  1530.    265 T2=Y:A=T1
  1531.    270 YM=YM-1
  1532.    280 A=A+YM:IF A<T2 THEN 300
  1533.    290 A=A-T2:T1=A:XM=XM+1:A=X:C=0:A=A+EL%:IF A>255 THEN A=A-256:C=1
  1534.    295 X=A:A=T2:A=A+EH%+C:T2=A:A=T1
  1535.    300 DRAW1, X0+XM, Y0-YM
  1536.    310 YM=YM-1:IF YM>=0 THEN 280
  1537.  
  1538. XM and YM are the x and y coordinates of the point to be plotted.  Note
  1539. that in line 200 X starts at 128, and this again is to round up all our
  1540. calculations; compare to line 20, where we started T2 at 0.5.  In the
  1541. above code I store T2 in the X and Y registers for the first part of the
  1542. code.  Note that in lines 220 and 290 there is some extraneous code to
  1543. simulate things that in assembly are taken care of by the 6502.  Note
  1544. also that the comparison in line 260 has been changed from < to <=.  This
  1545. makes the branch easier, and I'm not sure how it affects the calculation
  1546. (I didn't notice any difference in the few runs I tried it on).
  1547.  
  1548. Moving through the code, we increase x, and then add the decimal
  1549. part of E to the counter.  Then we add the integer part of E to the counter,
  1550. along with any carries.  If the integer part of the counter is greater than
  1551. y, it is time to decrease y and reset the counter.
  1552.  
  1553. Moving to the second part of the code, we do a little rearranging
  1554. in line 265.  Really a better thing to do would be to let A=T1-T2, so that
  1555. the compare in line 280 becomes simpler.  Anyways, note that the Y register
  1556. becomes freed up at this point.  From here on, it is pretty much the same
  1557. thing as before.
  1558.  
  1559. The full assembly code is then:
  1560.  
  1561.    ;Ellipse SLJ 11/3/95 Assumptions:
  1562.    ;0->XM B->YM, x- and y-coordinates
  1563.    ;0->T1
  1564.    ;EL and EH contain remainder and integer parts of E, resp.
  1565.  
  1566.    LDX #128
  1567.    LDY #00
  1568.    CLC
  1569. L1 INC XM
  1570.    TXA
  1571.    ADC EL
  1572.    TAX
  1573.    TYA
  1574.    ADC EH
  1575.    TAY
  1576.    ADC T1
  1577.    CMP YM
  1578.    BCC :CONT1
  1579.    SBC YM
  1580.    DEC YM
  1581. :CONT1   STA T1
  1582.    JSR PLOT
  1583.    CPY YM
  1584.    BCC L1
  1585.  
  1586.    STY T2
  1587.    LDA T1
  1588.    SBC T2
  1589.    DEC YM
  1590. L2 ADC YM
  1591.    BCC :CONT2
  1592.    SBC T2
  1593.    STA T1
  1594.    INC XM
  1595.    TXA
  1596.    ADC EL
  1597.    TAX
  1598.    LDA T2
  1599.    ADC EH
  1600.    STA T2
  1601.    LDA T1
  1602. :CONT2  JSR PLOT
  1603.    DEC YM
  1604.    BPL L2      ;Assuming y<128
  1605.  
  1606.  
  1607. #(A): Logarithms
  1608.  
  1609. Finally, we need a way of calculating b^2/a^2.  I suggest using
  1610. logarithms for this.  I do believe I discussed this concept in an earlier
  1611. issue of C=Hacking.  Nevertheless, the idea is that if
  1612.  
  1613.    x = b^2/a^2
  1614.  
  1615. then
  1616.  
  1617.    log(x) = 2*log(b) - 2*log(a)
  1618.  
  1619. so that
  1620.  
  1621.    x = exp(2*(log(b) - log(a))
  1622.  
  1623. Thus, three tables need to be created: one for log(x), and one each for
  1624. the integer and remainder parts of e^(2*x).  Now, to improve accuracy,
  1625. the first table might be a table of f(x)=222/log(128) * log(x/2).  This
  1626. constant is chosen so that f(255) is roughly 255.  222 was chosen because
  1627. the inversion (i.e. the e^x part) works best at that value.  This pretty
  1628. much assumes that x is not zero or one, either.  You can of course use
  1629. more tables for somewhat better accuracy.
  1630.  
  1631. One really nice thing about this is that you don't have to worry
  1632. about squaring things, since that part can be taken care of automatically
  1633. in logarithm space.  On the downside, we are restricted even further by
  1634. the types of numbers we can divide (e.g. log(a)-log(b) can't be larger
  1635. than 127 or so).
  1636.  
  1637. Division then consists of a table lookup, subtraction of another
  1638. table lookup, and two more table lookups.  Here is a short program to
  1639. demonstrate the use of logs in this sort of division, and a very rough
  1640. feel for the type of accuracy to expect -- note that it doesn't compare
  1641. decimal parts, or convert the decimal parts into fractions of 256, etc.:
  1642.  
  1643.    1 FAST:PRINT"[CLR]"
  1644.    10 DIM L(256),EI(256),ER(256):FC=222/LOG(128)
  1645.    20 FOR I=1 TO 256
  1646.    25 PRINT "[HOME]"I
  1647.    30 L(I)= INT(FC*LOG(I/2)+0.5):IF I=1 THEN L(I)=0
  1648.    40 S=I:IF I>127 THEN S=I-256
  1649.    50 EX=EXP(2*S/FC):IF EX>256 THEN PRINT"WHOOPS! EX="EX"I="I
  1650.    60 EI(I)=INT(EX+0.5)
  1651.    70 ER(I)=EX-EI(I)
  1652.    80 NEXT I
  1653.    90 EI(0)=1:ER(0)=0
  1654.    100 FOR A=2 TO 250
  1655.    110 FOR B=2 TO 250
  1656.    120 X=L(B)-L(A)
  1657.    123 IF X>127 THEN PRINT"OOPS:A="A"B="B"X="X
  1658.    126 IF X<0 THEN X=X+256
  1659.    130 A1=EI(X)+ER(X):A2=B*B/(A*A):IF A2>255 THEN B=600
  1660.    135 BL=INT(A2+0.5)-INT(A1+0.5)
  1661.    140 PRINT A;B,A1;A2,"ERR="INT(A2+0.5)-INT(A1+0.5)
  1662.    150 NEXT:NEXT
  1663.  
  1664. #(A): Conclusion
  1665.  
  1666. Sorry, no 3D graphics this time around.  Watch for a full-screen, hires
  1667. bitmapped solid 3D virtual world sometime in the not too distant future.
  1668. Otherwise, may your ellipses never be square :).
  1669.  
  1670.  
  1671. ============================================================================
  1672.  
  1673. #(@)surf: Hack Surfing
  1674.  
  1675. For those who can access that great expanse of area called the World Wide
  1676. Web, here is some new places to visit that are of interest to the Commodore
  1677. community.  In early 1994, when the US Commodore WWW Site started, the number
  1678. of sites online that catered to Commodore numbered in the 10's.  Now, the
  1679. number is in the 100's.  What a change.
  1680.  
  1681. If you know of a site that is not listed here, please feel free to send it
  1682. to the magazine.  The following links have been gleaned from those recently
  1683. changed or added to the US Commodore WWW Site Links page 
  1684. (http://www.msen.com/~brain/cbmlinks.html).  
  1685.  
  1686. To encourage these sites to strive to continually enhance their creations,
  1687. and because we like to gripe :-), we'll point out an improvements that 
  1688. could be made at each site. 
  1689.  
  1690. #(A): Companies
  1691.  
  1692. o  http://www.escom.nl
  1693.    ESCOM Interactive, Inc. The new home of Commodore has links to many of
  1694.    its offices and some general information.  The pages are still under 
  1695.    construction, but you should probably save this address.  C=Hacking gripe:
  1696.    No Commodore 8-bit inforation yet.
  1697.  
  1698. o  http://www.msen.com/~brain/guest/cmd/
  1699.    Creative Micro Designs.  Stay tuned to this site for information on
  1700.    the accelerator, and keep up to date on the latests prices on CMD
  1701.    peripherals and software.  C=Hacking gripe: For a comapny wanting having
  1702.    just announced the Super64CPU, no mention of it is to found anywhere on
  1703.    the WWW site.  Bummer.
  1704.  
  1705. #(A): Publications
  1706.    
  1707. o  http://www.softdisk.com/about/c64.html
  1708.    LOADSTAR and LOADSTAR 128.  If you are interested in LOADSTAR, check 'em
  1709.    out here.  Some Commodore links are included, and the and a few magazine 
  1710.    teasers are present.  In addition, details on how to ordr LOADSTAR or any
  1711.    of its related software titles is provided.  C=Hacking gripe:  the 
  1712.    background color.  Yellow is hard on our eyes...  Oh well.
  1713.    
  1714. o  http://www.mds.mdh.se/~dat95pkn/8bitar/
  1715.    Atta Bitar (8 Bitter) magazine.  Full indexes for the past 3 years, as well
  1716.    as information on how to subscribe.  We'd tell you more, but none of us
  1717.    read German (At least we THINK it's German), and the English transmation 
  1718.    page isn't done yet.  Anyway, if you would like to subscribe or need to 
  1719.    search the index of the magazine, here's the place to go.  
  1720.    C=H gripe: Yes, we know this is English-centric, but we just wish we could
  1721.    actually read all the great info on this site.
  1722.    
  1723. #(A): User's Groups
  1724.  
  1725. o  http://www.cucug.org/
  1726.    Champaign-Urbana Commodore User's Group.  Home of the Universtity of
  1727.    Illinois (the editor's alma mater!)  Meeting dates and time, along with 
  1728.    newsletters and a user group listing are presented.  C=H gripe: No 
  1729.    mention of what local CBM 8-bit users are doing.  This site recently 
  1730.    changed addresses, so change all your links...
  1731.    
  1732. o  http://www.psc.edu/~eberger/pcg/
  1733.    Pittsburgh Commodore Group.  Local news, meeting dates and time, and 
  1734.    some newsletters are present.  This site has also recently relocated
  1735.    to this new address.  C=H gripe: Same as for CUCUG.  We want to know
  1736.    what the CBM 8-bitters are doing in Pittsburgh.
  1737.    
  1738. o  http://www.slonet.org/~rtrissel/
  1739.    The Central Coast Commodore User's Group.  Those in the Santa Maria
  1740.    CA area will be glad to know that CCCUG is there for them.  Past
  1741.    newsletter are available, and some links to other information of 
  1742.    interest is present.  C=H gripe: Meeting dates and times need to be
  1743.    present in some easy place.  C=H plug:  It sounds like this club might
  1744.    need a little help, as it is down on members.  If you are in the Santa
  1745.    Maria area, consider joining...
  1746.  
  1747. #(A): Miscellaneous
  1748.  
  1749. o  http://www.byte.com/art/9408/sec14/art1.htm
  1750.    Byte Magazine's Commodore obituary, by Tom Halfhill.  Tom spells out many
  1751.    of the things that Commodore DID do right in its lifetime, and reflects
  1752.    on the blunders CBM made.  The article makes for very good reading, but 
  1753.    will depress some.  C=H gripe: The pictures in the real article aren't
  1754.    reproduced in the WWW page.
  1755.  
  1756. o  http://stud1.tuwien.ac.at/~e9426444/geoswarp/index.html
  1757.    GEOS Warp 1.0.  For the Mac user who needs or wants to run GEOS, this
  1758.    program, run on a Macintosh, will allow GEOS programs to operate on
  1759.    the Mac.  The system looks very impressive, to the point of us not asking,
  1760.    Why?  C=H gripe:  Not really with the page, but the writer laments that
  1761.    progress is slow owing to no agreement with GEOWorks.  Such things may
  1762.    doom the project to failure.
  1763.  
  1764. o  http://vanbc.wimsey.com/~danf/cbm/
  1765.    Dan Fandrich's WWW Site.  For those who develop on alternate platforms or
  1766.    use multiple programming languages with the C64/128, bookmark this page.  
  1767.    Very current info, and lots of it is presented.  Some defunct Commodore 
  1768.    mags are indexed, and pointers are provided to many of the current crop of 
  1769.    magazines, including this one.  C=H gripe:  the page needs a little bit 
  1770.    more organization to make it easier to get at juicy info.
  1771.  
  1772. o  http://www.aloha.net/~scatt/commodore.htm
  1773.    Scatt's WWW Site. For those just moving into assembly language programming
  1774.    from BASIC or something else, this page has a beginner's tutorial you
  1775.    might find useful.  C=H gripe: A little low on content, but we are glad 
  1776.    what there is is available.
  1777.  
  1778. o  http://www.cs.wm.edu/~pbgonz/progc64.html
  1779.    Pete Gonzalez's WWW Site.  Small page, but worth viewing.  Pete shows some
  1780.    screen shots of a new game he is developing, and offers copies of his 
  1781.    in progress cross assembler for the PC.  C=H gripe: When's the game coming
  1782.    out again? :-)
  1783.  
  1784. o  http://www.ts.umu.se/~yak/cccc/
  1785.    The Commodore Computer Cult Corner.  Some people play games, and then some
  1786.    people PLAY games.  Jonas Hulten has pictures of his game design, 
  1787.    implementation, and programming heoes.  You can read about each one, and
  1788.    even light a "candle" for them.  This site has a CBM links page, which 
  1789.    anyone can add their link to automatically.  C=H gripe: We can add our home
  1790.    page automatically, but not our hero.  
  1791.  
  1792. o  http://www.slonet.org/~jwilbur/
  1793.    John Wilbur's WWW Site.  Basically, just a links page right now, but we'll
  1794.    check back.  C=H gripe: We'd like to see a little more about John as it
  1795.    relates to Commodore.
  1796.  
  1797. o  http://www.student.informatik.th-darmstadt.de/~supermjk/
  1798.    Marc-Jano Knopp's WWW Site.  Mainly a large links page for Commodore
  1799.    information, this site does give a glimpse of the never produced Commodore
  1800.    LCD laptop computer.  C=H gripe:  As above, we love to see a little more
  1801.    about Marc-Jano as it relates to Commodore.
  1802.  
  1803. ============================================================================
  1804.  
  1805. #(@)zedace: Design and Implementation of an Advanced Text Editor 
  1806.             by Craig Bruce (csbruce@ccnga.uwaterloo.ca)
  1807.  
  1808. Note: Due to the size of the article, no executable or source code 
  1809.       is included, but both will be included in ACE Release #15 
  1810.       (ftp://ccnga.uwaterloo.ca/pub/cbm/os/ace/).
  1811.  
  1812. #(A)1: 1. INTRODUCTION
  1813.  
  1814. This article discusses the design and implementation of the ZED text editor
  1815. for the ACE operating system (Release #15 and higher).  The program and full
  1816. source code will be freely available when they are ready.  ZED is written
  1817. entirely in assembly language (ACEassembler) and makes heavy use of the
  1818. full-screen control capabilities of ACE.  However, part of the genius of the
  1819. design of the ACE interface is that its facilities could be replicated into
  1820. a standalone environment and a new ZED could be made into a one-part program
  1821. (for greater convenience, with less flexibility).
  1822.  
  1823. There was a previous version of ZED, which WAS a standalone program.  It was
  1824. written entirely in _machine_ language (as opposed to assembly language;
  1825. y'know, hexadecimal and stuff, with a machine-language monitor).  Needless
  1826. to say, upgrading and maintaining the program was a real problem, even
  1827. though it was only 17K in size.  The program also had a couple of
  1828. limitations, the most serious of which being that all lines were limited to
  1829. a maximum of 80 characters (plus a carriage return), or they would be split
  1830. into two physical lines internally.  It would also work only on the
  1831. 80-column C128.
  1832.  
  1833. Still, the standalone version had a number of outstanding capabilities,
  1834. including the ability to edit EXTREMELY large files with an REU and dynamic
  1835. data structures, the ability to use "burst mode" on devices that supported
  1836. it, TAB and character-set translation on loading and saving, global search
  1837. and replace, range delete and recall, and a paragraph "juggling" feature.
  1838. It is truly an outstanding program (if I do say so myself), and it is my
  1839. pleasure to use it every day.  (I also use Unix's "vi" every day, and I am
  1840. getting tired of its clumsy user interface... I may just have to port ZED to
  1841. the Unix environment one of these days).
  1842.  
  1843. The ACE version has/will have all of these features and then some.  The ACE
  1844. version supports even larger files by using the ACE dynamic memory
  1845. management system (see C= Hacking #7 or a newer ACE Programmer's Reference
  1846. Guide) in addition to its own byte-oriented memory management (see C=
  1847. Hacking #2) with internal memory (up to 512K on a C128), REUs up to 16 Megs,
  1848. and RAMLink DACC memory up to 16 Megs.  Burst-mode support isn't currently
  1849. available in ACE (see C= Hacking #3), nor does the ACE version of ZED
  1850. currently implement the other outstanding editing features of the original
  1851. ZED mentioned above.  (For another C= Hacking reference, ACE does support a
  1852. three-key rollover for typing convenience (see C= Hacking #6)).
  1853.  
  1854. However, the ACE version supports extremely long physical lines (paragraphs)
  1855. by providing automatic word wrapping and "soft returns" with automatic "text
  1856. sloshing" (a dynamic form of "juggling"), and it therefore has/will have the
  1857. functionality of a word processor.  The new version also works in all video
  1858. modes that ACE supports on both the C128 and C64.
  1859.  
  1860. #(A)2: 2. DATA STRUCTURES, FILE LOADING
  1861.  
  1862. Now we start talking about the implementation of ZED.  What a text editor
  1863. is, basically, is a program that holds a text document in memory that allows
  1864. you to use certain commands to alter tiny pieces or large-scale chunks of
  1865. the document and then to save the changed document permanently back to
  1866. disk.  The way in which the document is held in memory is the content of
  1867. this section.
  1868.  
  1869. #(A)2.1: 2.1. DOCUMENT DATA STRUCTURE
  1870.  
  1871. ZED uses a bi-directionally linked list to hold the text document in
  1872. memory.  A special "trailer" line is used (which is displayed with a little
  1873. "house" character on it) to make modifications to the linked list and the
  1874. whole list is in the form of a big ring (the links run around in circles).
  1875. Here is an asciigram of a document with two data lines:
  1876.  
  1877.   /-------------------\
  1878.   |   /----------\    |
  1879.   |   |          V    |
  1880.   |   |        +-------------------------------------
  1881.   |   |        |next|prev|  data for line #1...
  1882.   |   |        +-------------------------------------
  1883.   |   |          |    ^
  1884.   |   |          V    |
  1885.   |   |        +-------------------------------------
  1886.   |   |        |next|prev|  data for line #2...
  1887.   |   |        +-------------------------------------
  1888.   |   |          |    ^
  1889.   |   |          V    |
  1890.   |   |        +-------------------------------------
  1891.   |   |        |next|prev|  special trailer line...
  1892.   |   |        +-------------------------------------
  1893.   |   |          |    ^
  1894.   |   \----------/    |
  1895.   \-------------------/
  1896.  
  1897. I should mention that all pointers are 32-bit values, so that they can point
  1898. to anywhere in ACE's "far" memory.  (In fact, many of the control variables
  1899. for ZED are 32 bits in size, to avoid all arbitrary restrictions on the
  1900. magnitudes of various things).  And, despite where the arrows point in the
  1901. diagram, the value that is stored for the pointer is the address of the
  1902. starting byte of the record that is being pointed to.
  1903.  
  1904. I should also mention that lines are stored as they are displayed.  If one
  1905. physical line (terminated by a carriage return) has to be split (using "soft
  1906. returns") over multiple display lines, then each _display_ line takes up one
  1907. linked-record position in the document data structure.
  1908.  
  1909. Using a bi-directionally (doubly) linked list (instead of a uni-directionaly
  1910. (singly) linked list is a practical necessity in this environment for two
  1911. reasons.  First, the linking represents the natural way that the user
  1912. accesses the document: he normally moves cursor up and down, page up and
  1913. down.  It would take a lot of time to move the cursor up using a singly
  1914. linked list.  Second, using a double linked list makes it easier to insert
  1915. or delete a line from the document.  You need to modify the previous record
  1916. to point beyond the record being deleted, but the previous record is
  1917. difficult to locate in a singly linked list; you must keep and manage a
  1918. pointer to it (and if the user moves the cursor up, you lose what you've got
  1919. for it).  I prefer doubly liked lists for any job anyway, even if the
  1920. ability to go backwards isn't needed, because they are easier to work with
  1921. (and to construct reusable library routines for).
  1922.  
  1923. Using a large block of memory for the data isn't really an option either.
  1924. Anyone who has used SpeedScript knows what happens when you try to insert
  1925. text near the beginning of a long document: it takes a lot of time to insert
  1926. one space in the document memory, and the delay is annoying.  Imagine this
  1927. played out for a document that is N megabytes in size.  (Some auxiliary data
  1928. structure would be needed in this case anyway, to break the 64K barrier).
  1929. I'm guessing that most other word processors/text editors for Commodore
  1930. computers use this data structure (a "large" block of memory).
  1931.  
  1932. The decision to store each display line in a single record is really one of
  1933. convenience and efficiency.  Most of the time, the use will be positioning
  1934. the cursor and whizzing between display pages, so we don't want to be
  1935. wasting any time uselessly re-formatting the text while he (sic) is doing
  1936. this.  We only want to re-format the text when an actual modification is
  1937. made to the document.  This organization does have the ugly implication that
  1938. physical and logical line numbers may not always match up, but if the
  1939. "target" line length (the maximum length that a single display line can be)
  1940. is set to be longer than the maximum physical-line length of a file (often
  1941. 80 characters), then the two will match up.
  1942.  
  1943. Accessing the document is fairly simple.  All that we need to locate the
  1944. entire document is the address of the special trailer line.  With this, we
  1945. know directly where the bottom line is, so we can instantly go to the bottom
  1946. of the document (Commodore-DOWN) and then follow the links backward to
  1947. access preceeding lines.  Finding the top of the document is also quite easy
  1948. since the document is in a ring.  We just locate the trailer line and then
  1949. follow the "next" link, and we arrive at the first line (Commodore-UP).  It
  1950. should be no surprise that a pointer is kept to the trailer line in ZED in
  1951. order to locate a document.  The design allows for many documents to be held
  1952. in memory at the same time, including the "kill buffer" (which is logically
  1953. a complete and independent document).  To make management even simpler, it
  1954. should be noted that this trailer line never changes (therefore, we never
  1955. have to update the pointer to the trailer line of a document).
  1956.  
  1957. #(A)2.2: 2.2. LINE DATA STRUCTURE
  1958.  
  1959. The format of each individual display line within a document held in the
  1960. linked-list structure described above is as follows:
  1961.  
  1962. OFF   SIZ   DESC
  1963. ---   ---   -----
  1964.   0     4   pointer to the next line
  1965.   4     4   pointer to the previous line
  1966.   8     1   flags for the line, including $80=hard-return, $40=trailer line
  1967.   9     1   number of characters on the line 
  1968.  10     n   the displayable characters of the line
  1969. n+10    -   SIZE
  1970.  
  1971. The two 32-bit pointers have already been mentioned.  The "flags" field
  1972. tells whether the line ends in a "hard return" or a "soft return".  A hard
  1973. return (indicated by the $80 bit being set) is recorded for every place in
  1974. the text file where a carriage-return character is present.  A soft return
  1975. (indicated by the $80 bit being clear) is formatted into the document every
  1976. place where a line must be broken in order to avoid it exceeding the target
  1977. line length.  If you modify the document, then words can be wrapped and
  1978. pulled back around a soft return in order to insure that display lines are
  1979. as full as possible (whereas they cannot be wrapped around a hard return).
  1980.  
  1981. When a file is being written back to disk, lines that have a hard return
  1982. flag will be written with a trailing carriage-return character, whereas
  1983. lines ending with a soft return will be written with only the characters
  1984. displayed on the line (no CR), and, as such, they will be logically
  1985. concatenated together into the same physical line (again) in the output
  1986. file.  The "trailer line" flag indicates whether the current line is the
  1987. special trailer line of the document or not.  We need a convenient way to
  1988. check for running into the trailer line, and we cannot use null pointers
  1989. since the document is in a ring (note that there won't be any null pointers
  1990. even if the document contains zero data lines; the trailer line will point
  1991. to itself).
  1992.  
  1993. The lower six bits of the flags field are currently unused, but they could
  1994. be used, for example, to record the number of leading spaces that a
  1995. line has before the first non-blank character.  This would allow us to
  1996. hold a file with a lot of indentation (a program, for example) using less
  1997. memory per line.  This feature is not currently implemented.
  1998.  
  1999. The next field tells the number of displayable characters that are on the
  2000. line and then the next field stores the actual characters in a simple
  2001. string.  If the line ends in a hard return, then the carriage-return
  2002. character is NOT stored in the line data, since its presence is already
  2003. indicated in the line header.  When records are allocated in the
  2004. dynamic-memory space, only the number of bytes that are actually needed are
  2005. allocated.  This is the number of bytes on the line plus ten bytes for the
  2006. line header.  Actually, the number of bytes reserved for an allocation is
  2007. the number of bytes requested rounded up to the nearest multiple of eight
  2008. bytes, for technical reasons discussed in C= Hacking #2.  A single display
  2009. line can contain up to 240 characters (not counting the CR).
  2010.  
  2011. Every time that a line needs to be accessed, it must be fetched from far
  2012. memory into a buffer in the program space.  There is a slight efficiency
  2013. problem in accessing a line that there isn't when allocating and storing a
  2014. line.  When going to read the line, you don't know how big it is, since you
  2015. know nothing about it other than its far location.  The conservative thing
  2016. to do would be to read the first ten bytes of the line record (the header
  2017. information) and then use the value in the line-length field to figure out
  2018. how many more bytes you need to fetch.  I kind of took a wild stab and made
  2019. it so that I read the first twenty bytes of a line and then see if the line
  2020. has ten or fewer displayable characters on it.  If so, then I have
  2021. successfully fetched the whole line and I am done in one access.  (Note that
  2022. there is no problem with fetching far memory beyond one record's allocation
  2023. (although there certainly would be a problem with stashing)).  If not, then
  2024. I fetch the remaining characters and I am done in two fetches (actually, I
  2025. fetch all of the characters for simplicity).
  2026.  
  2027. However, often times I don't actually have to fetch the data of a line at
  2028. all and I only need to access its header information (to follow or change
  2029. its linkage, for example).  In this case, I only have to access the header
  2030. of the line and I only need one access to get it since I already know how
  2031. long the header is (ten bytes).  I can also write back a modified header in
  2032. place since it is of fixed length.  If I were to, for example, add
  2033. characters to a line, then I would have to re-allocate a larger line record
  2034. for it, free the old line-record storage, and link the new line record in
  2035. with the rest of the document (by updating the previous record's "next"
  2036. pointer and updating the next record's "prev" pointer and by updating any
  2037. necessary global variables... quite a bit or work).
  2038.  
  2039. #(A)2.3: 2.3. GLOBAL VARIABLES
  2040.  
  2041. This section describes all of the global variables that ZED keeps in order
  2042. to edit a document.  First, I have three separate temporary-storage work
  2043. areas:
  2044.  
  2045. work1 = $02 ;(16)  ;used by malloc
  2046. work2 = $12 ;(16)  ;used by file-load
  2047. work3 = $22 ;(14)
  2048.  
  2049. Each work area is used by successively higher levels of software in order to
  2050. avoid conflicts between layers.  For example, "work1" is used by the
  2051. dynamic-memory routines and "work2" gets modified when loading a file.  The
  2052. process of loading a file involves a lot of memory-allocation work, so it is
  2053. good that they use separate working storage and don't clobber each other.
  2054.  
  2055. The following variables are used for managing the screen and the current
  2056. cursor column:
  2057.  
  2058. scrTopAddr      = $30 ;(2)  ;screen address of the top line on the display
  2059. scrRow          = $34 ;(1)  ;row number of the current line on the display
  2060. scrCol          = $35 ;(1)  ;virtual screen column number of cursor position
  2061. scrRows         = $36 ;(1)  ;number of rows on the display
  2062. scrCols         = $37 ;(1)  ;number of columns on the display
  2063. scrStartRow:    .buf 1      ;starting row on the display
  2064. scrStartCol:    .buf 1      ;starting column on the display
  2065. scrRowInc       = $38 ;(1)  ;row increment for the display
  2066. scrLeftMargin   = $39 ;(1)  ;left margin for displaying lines
  2067. statusMargin:   .buf 1      ;left margin of the status line on the display
  2068. conColor:       .buf 8      ;color palette
  2069.  
  2070. Most of these fields are used for interfacing with ACE's direct-access
  2071. full-screen-control calls.  The ones that are used most often are allocated
  2072. to zero-page locations (to reduce code size and to increase performance) and
  2073. the others are allocated to absolute memory.  ACE allows application
  2074. programs to use zero-page locations $02 to $7F for their own purposes.
  2075.  
  2076. The current displayed cursor location is stored in "scrRow" and "scrCol".
  2077. "scrRow" is the current physical display row of the current document line
  2078. (where display rows start at 2 since the control and separator lines take up
  2079. rows 0 and 1), and "scrCol" tells the current position on the current line,
  2080. from 0 up to the length of the line.  Since this version of ZED features
  2081. horizontal scrolling to handle really long display lines, "scrLeftMargin" is
  2082. also maintained to tell what the column number of the left margin of the
  2083. display is.  When we refresh the screen, we will display all lines starting
  2084. from this character position.  Note that internally, column numbers start
  2085. from 0 whereas they are numbered starting from 1 in all dialogue with the
  2086. ape at the keyboard.  Every time that the cursor could possibly move off the
  2087. right or left edge of the screen, a check is made and if this happens, then
  2088. the "scrLeftMargin" is adjusted and the screen is re-painted (effectively
  2089. giving us horizontal scrolling).
  2090.  
  2091. The following variables are used to keep track of various parameters:
  2092.  
  2093. targetLen       = $3a ;(1)  ;length to display lines
  2094. wrapFlag        = $3b ;(1)  ;$80=wrap,$40=showCR
  2095. modified        = $3c ;(1)  ;$00=no, $ff=modified
  2096. modeFlags       = $3d ;(1)  ;$80=insert, $40=indent
  2097. statusUpdate    = $3e ;(1) ;128=line,64=col,32=mod,16=ins,8=byt,4=fre,2=nm,1=msg
  2098. markedLinePtr:  .buf 4      ;line that is marked, NULL of none
  2099. markedLineNum:  .buf 4      ;line number that is marked
  2100. markedCol:      .buf 1      ;column of marked logical line
  2101.  
  2102. "targetLen" is the length that ZED tries to keep wrappable lines as close to
  2103. without exceeding.  By default, it will be set to the physical display width
  2104. of the screen, but it can be set to 240 characters by the "-l" option and it
  2105. will eventually be manually settable to any value you want (10<=l<=240).
  2106. The "wrapFlag" tells, first, whether word wrapping should be used ($80 set)
  2107. or whether lines should just be broken at the target length regardless of
  2108. whether it gets broken in the middle of a word or not ($80 clear), and
  2109. second, tells whether carriage-return characters should be displayed to the
  2110. user ($40 set) or not ($40 clear).  (Actually, a suitable character to
  2111. represent the carriage return is displayed, taken from the graphical palette
  2112. of the current character set).  You will normally want carriage returns
  2113. displayed when you are using ZED as a word processor, and you will normally
  2114. want them not displayed when using ZED as a text editor.
  2115.  
  2116. The "modeFlags" tell, first, whether auto-insert ($80 bit set) or over-type
  2117. ($80 clear) mode is in effect, and second, whether auto-indent ($40 set) or
  2118. no-indent ($40 clear) mode is in effect.  Insert/overtype is currently
  2119. supported and auto-indent is not.  Auto-indent is intended to eventually
  2120. make programming easier by not requiring you to type a bunch of spaces to
  2121. indent a new line of a source file that should be at the same nesting level
  2122. as the previous line.
  2123.  
  2124. The "statusUpdate" variable is used to reduce the amount of work the needs
  2125. to be done in order to keep the status line at the top of the screen up to
  2126. date.  If any of the variables that control the values displayed on the
  2127. status line change, then the corresponding bit in this variable should be
  2128. set.  After processing a keystroke but before waiting for the next
  2129. keystroke, ZED will update all of the fields that have a '1' bit in this
  2130. variable.  The "msg" bit is special, since it tells whether a dialogue
  2131. message is currently being displayed on the separator line (between the
  2132. status line and the first document line), and if there is, then the message
  2133. should be erased (overwritten by the separator characters) _after_ the user
  2134. presses the next key (since it wouldn't be much fun if the user had only a
  2135. couple of milliseconds to read the message).
  2136.  
  2137. The "marked*" fields tell where the "mark" is currently set for range
  2138. commands (like delete).  Like in the stand-alone ZED, I will be making this
  2139. version clear the mark after every modification to the file.  The main
  2140. reason for this is that it would be a pain in the but to keep track of the
  2141. mark in some cases like when the line that is marked gets deleted or
  2142. updated, and that having set-mark/do-operation clear the mark prevents the
  2143. ape at the keyboard from accidentally hitting a range-destroy key and wiping
  2144. out his document (he will get a "range not set" error message instead).
  2145.  
  2146. The following variables are used to keep track of the current position in
  2147. the document:
  2148.  
  2149. linePtr         = $40 ;(4)  ;pointer to current line
  2150. lineNum         = $44 ;(4)  ;number of current physical line
  2151. headLinePtr     = $4c ;(4)  ;pointer to the special header/trailer line
  2152. lineCount       = $50 ;(4)  ;number of display lines in buffer
  2153. byteCount       = $54 ;(4)  ;number of bytes in buffer
  2154.  
  2155. "linePtr" always points to the line record that the cursor is logically on.
  2156. This is probably the most important global variable.  This variable is
  2157. needed so that we know what line to modify/etc. if the user enteres a
  2158. letter/etc.  "lineNum" gives the line number of the "linePtr" line, where
  2159. line numbers start from 1.  This needs to be maintained in order to tell the
  2160. ape at the keyboard where in the document he is.  These two fields are
  2161. sequentially updated as the user moves from line to line in the document.
  2162.  
  2163. "headLinePtr" is a bit of a misnomer since it actually points to the special
  2164. trailer line.  As explained above, it is used to find the top and the bottom
  2165. of the document.  "lineCount" keeps track of the total number of display
  2166. lines in the current document, and "byteCount", the total number of bytes.
  2167. Each carriage-return character counts as one byte.  Keeping track of line
  2168. and byte counts is for convenience rather than necessity.
  2169.  
  2170. The following variables manage the "kill buffer", where text goes after it's
  2171. been deleted but before it's completely discarded (a sort of purgatory):
  2172.  
  2173. killBufHeadPtr: .buf 4      ;pointer to special header/trailer line of kill buf
  2174. killLineCount:  .buf 4      ;number of lines in kill buffer
  2175. killByteCount:  .buf 4      ;number of bytes in the kill buffer
  2176.  
  2177. The kill buffer is maintained in exactly the same structure that the main
  2178. document is: a ring of doubly linked line records.  The three fields shown
  2179. store the pointer to the special trailer line, the number of data lines in
  2180. the kill buffer, and the number of data bytes in the kill buffer,
  2181. respectively.
  2182.  
  2183. In addition to the kill buffer, there is also a "rub buffer":
  2184.  
  2185. RUB_BUFFER_SIZE = 50
  2186. rubBufPtr:  .buf 1
  2187. rubBufSize: .buf 1
  2188. rubBuffer:  .bss RUB_BUFFER_SIZE
  2189.  
  2190. It is used to hold the fifty single characters that have most recently been
  2191. deleted by using either the DEL or Commodore-DEL (Rub).  I found that when
  2192. using the old version of ZED, I would sometimes unintentionally delete a
  2193. single character and then want it back, and I had to expend mental effort to
  2194. figure out what it was.  This mechanism takes the effort out of that job by
  2195. maintaining a LIFO (Last In First Out) (circular) buffer controlled by the
  2196. variables given above (note that "RUB_BUFFER_SIZE" is a constant which can
  2197. be easily changed up to 255 in the source code).  The "rubBuffer" is
  2198. actually contained in the uninitialized-storage section of the program
  2199. ("bss" in Unix terminology).  (The ".bss" directive is not currently
  2200. implemented in the ACEassembler, but I used it here as a shorthand for the
  2201. equates that replace it).
  2202.  
  2203. The Shift-Ctrl-R (rub recall) keystroke is used to recall the previous
  2204. character (as if you had typed it in) and has the effect of resetting the
  2205. "rubBufPtr".  Then, each additional time that you type Shift-Ctrl-R in a
  2206. row, the "rubBufPtr" is advanced backward to the character previous to
  2207. the one just recalled.  Pressing anything other than Shift-Ctrl-R resets
  2208. the "rubBufPtr", so that you could recall the characters again, if you want.
  2209. You can recall as few characters as you wish.
  2210.  
  2211. Interpreting command keys is done with the following global variables:
  2212.  
  2213. keychar       = $58 ;(1)
  2214. keyshift      = $59 ;(1)
  2215. sameKeyCount: .buf 1
  2216. sameKeyChar:  .byte $00
  2217. sameKeyShift: .byte $ff
  2218.  
  2219. ACE returns both a shift pattern and a key character code, so both are
  2220. stored.  The shift pattern allows us to take different actions for commands
  2221. like Ctrl-R and Shift-Ctrl-R.  The "same*" fields store the previous
  2222. keystroke and the number of times that the exact keystroke has been made, so
  2223. that slightly different actions can be taken when the same keystroke is made
  2224. multiple times, such as with Shift-Ctrl-R (or maybe HOME).
  2225.  
  2226. The following global variables are also maintained for various purposes:
  2227.  
  2228. exitFlag:     .buf 1
  2229. arg:          .buf 2
  2230. temp:         .buf 4
  2231. stringbuf:    .bss 256
  2232. filebuf:      .bss 256
  2233. tpaFreemap:   .bss 256
  2234. linebuf:      .bss 256
  2235. line          = linebuf+headLength ;(241)
  2236. headBuffer    = $70 ;(10) ;buffer for holding the head of the current line
  2237. headNext      = $70 ;(4)  ;pointer to the next line in a document
  2238. headPrev      = $74 ;(4)  ;pointer to the prev line in a document
  2239. headLineLe    = $78 ;(1)  ;length of the text line
  2240. headFlags     = $79 ;(1)  ;$80=CR-end, $40=headerLine, &$3F=indent
  2241. headLength    = 10        ;length of the line header
  2242. documentBuf:  .bss 256
  2243.  docbufNext   = documentBuf+0   ;(4)
  2244.  docbufPrev   = documentBuf+4   ;(4)
  2245.  docbufInfo   = documentBuf+8   ;(23)
  2246.  docbufFilenameLen = documentBuf+31 ;(1)
  2247.  docbufFilename= documentBuf+32  ;(224)
  2248.  
  2249. "exitFlag" is set to tell the main loop to bail out and exit back to the
  2250. calling program.  "arg" is used for scanning the command-line arguments.
  2251. "temp" is used miscellaneously.  "stringbuf" is used for miscellaneous
  2252. string processing, and "filebuf" is used for miscellaneous file/string
  2253. processing.  "tpaFreemap" is used by the dynamic-memory-management code as a
  2254. free-memory-page map for making allocations out of the application program
  2255. area (or TPA, Transient Program Area).  The ACE kernel doesn't dynamically
  2256. allocate pages in the application space (since this cannot normally be done
  2257. reliably), so a mechanism is needed inside of ZED to make use of this
  2258. memory.
  2259.  
  2260. "linebuf" is the place where the current line is fetched to/stashed from
  2261. when it is being accessed or modified.  "line" is the sub-field of "linebuf"
  2262. where the actual line data is stored.  The "head*" variables are allocated
  2263. in zeropage and the record-header information from "linebuf" is copied to
  2264. these variables whenever a line is fetched and copied from these variables
  2265. when a line is stashed to far memory.  Zero page is used for these variables
  2266. since they are manipulated all of the time.
  2267.  
  2268. Finally, "documentBuf" stores all of the information about the current main
  2269. document.  There is currently support for only one main document
  2270. implemented, but the design includes the concept of the user being able to
  2271. switch between an arbitrary number of documents held in memory at any time.
  2272.  
  2273. 2.4. LOADING A FILE
  2274.  
  2275. When ZED is first started up, its usual first job is to load in the document
  2276. that was named on the command line (plus you can load a file at any time
  2277. with Ctrl-L).  ZED uses the standard ACE "open", "read", and "close" system
  2278. calls to do this, although there is a bit of business that has to happen to
  2279. get the data into the internal form that ZED uses.  The job is split into a
  2280. number of routines to make it easier to program.
  2281.  
  2282. The main routine opens the file for reading and initializes that variables
  2283. that the load routine uses.  Among other things, the load routine counts up
  2284. the number of display lines and physical bytes in the file and must wrap
  2285. physical lines into display lines while reading.  Later, this routine will
  2286. perform on-the-fly translation from other file formats to PETSCII and will
  2287. perform TAB expansion if requested.
  2288.  
  2289. The main routine repeatedly calls subroutines to read a line into the line
  2290. buffer, wrap it, and store it to memory.  For the purpose of the following
  2291. discussion, we will assume that the "target" line length is 80 characters,
  2292. although it can be set to anything that you want.  The Read routine copies
  2293. characters from the "filebuf" to the line buffer, with the filebuf being
  2294. re-filled with file-data characters as necessary in 254-byte chunks (the
  2295. natural size of Commodore data sectors, for efficiency).  Data bytes are
  2296. copied until either a carriage-return (CR) character is encountered or we
  2297. reach the 81st character (target+1).  We have to check the 81st character
  2298. because it may be a CR, and if we are in the normal text-editor mode, we can
  2299. store a full 80 data characters on a display line, even if it ends in a CR
  2300. (some editors, quite annoyingly, cannot do this).  However, if the user
  2301. selects the mode where CRs are visibly displayed on the screen, then we stop
  2302. scanning the current display line at a maximum of 80 characters if a CR
  2303. isn't encountered.
  2304.  
  2305. After the characters of the display line have been put into the line buffer
  2306. in the above step, it may be the case that the word at the end of the line
  2307. has been abruptly broken in the middle.  If the line ended in a CR, then
  2308. this doesn't need to be checked.  If the line didn't end in a CR and if the
  2309. "wrap" mode is currently on, then an abruptly cut word will have to be
  2310. wrapped to the next line.  To do this, we scan from the end of the line back
  2311. until we encounter the last space character on the line.  Then, we cut the
  2312. line immediately after that space, and remember where we cut it so that we
  2313. can later process the overflown characters.  If there is no space on the
  2314. line (i.e., the first and only word on the line is longer than the target
  2315. length), then we keep it as-is and end up breaking the word abruptly.  Note
  2316. that we break the line with a "soft return", so there is no damage done to
  2317. the data by word wrapping.
  2318.  
  2319. After the fat (if any) has been trimmed off the current display line, we
  2320. want to store it into far memory, into the doubly linked ring structure
  2321. discussed above.  To do this, we first, set the pointer to the previous line
  2322. to the address of the previous line record (we keep track of this) and set
  2323. the pointer to the next line to Null (for now).  Then we we allocate memory
  2324. for the current line and Stash it out.  But we're not done yet; we need to
  2325. set the "next" pointer on the previous line record to point to our newly
  2326. allocated line.  This can be done by simply writing the 32-bit pointer value
  2327. to the start address of the previous line (there is no need to re-fetch the
  2328. previous-line contents or header).
  2329.  
  2330. And after stashing out the line, we recall where we wrapped it (if we did)
  2331. and copy the characters that were cut off to the beginning of the line
  2332. buffer and we pretend that we have fetched these from the file as if in the
  2333. Load Line step above.  Then we go back to the Load Line step and continue.
  2334.  
  2335. When loading is finished (after we hit End-Of-File (EOF) on the file being
  2336. read), we flush the last incomplete line segment, if there was one (a file
  2337. is not required to end in a CR) and then we cap things off with the special
  2338. trailer line.  This trailer line is allocated before we start loading the
  2339. file (although I didn't mention it above), and now we set up its links so
  2340. that our entire file is the nice doubly linked ring that we like so much.
  2341. Now we are finished, and we return the trailer-line pointer, the number of
  2342. display lines read in, and the number of physical bytes read in to whomever
  2343. called us (it could be the command-line parser, the Ctrl-L (Load) command,
  2344. or the Ctrl-I (Insert) command).
  2345.  
  2346. There are three reasons why I like having this special trailer line around.
  2347. (1) It allows us to not have to worry about Null pointers.  For example, you
  2348. will notice that while stashing a loaded line, I allocated the trailer line
  2349. first so that we would always have a "previous" line to link with.  (2) It
  2350. allows the user to move the cursor beyond the physical end of the document
  2351. to do operations like recall (Ctrl-R) a block of text.  This was a problem
  2352. with the original ZED; you had to go the the end of the file, press RETURN
  2353. to open up a blank line, recall the text, and then delete the bogus blank
  2354. line.  (3) It allows a document to have zero characters in it in a
  2355. consistent fashion.
  2356.  
  2357. There is also a subtle but complicated issue dealing with dynamic memory
  2358. allocation that I haven't discussed yet: what if it fails?  (I.e., what if
  2359. we run out of memory?).  In this case, we must handle the failure
  2360. gracefully, maintain the integrity of the document as best we can, and
  2361. inform the user.  In some cases, maintaining the integrity will involve
  2362. un-doing committed changes to the document, which is a real pain in the
  2363. butt, but which is still very important.  It would be kind of annoying if
  2364. you just made the last keystroke on five hours of editing work and the
  2365. program aborted on an "out of memory" error, sending all of your work to the
  2366. great bit bucket in the sky.
  2367.  
  2368. #(A)3: 3. SCREEN DISPLAY, MOVING AROUND
  2369.  
  2370. This section discusses the operations that have to do with maintaining the
  2371. current secion of the document on the display and moving the cursor around
  2372. within the document.
  2373.  
  2374. #(A)3.1: 3.1. PAINTING THE SCREEN
  2375.  
  2376. This is the essential operation that keeps the screen up to date with the
  2377. docment in memory.  ZED has a single function that does this operation, and
  2378. it is called with the arguments: a pointer to the starting line to display,
  2379. the starting screen line number to start painting at, and the ending screen
  2380. line number to end painting at, plus one (lots of endings are 'plus one'
  2381. since this allows me to use the BCC instruction).  Some implied arguments
  2382. include general information about the screen for use with the "aceWin*"
  2383. kernel functions and the left margin for displaying lines.
  2384.  
  2385. This subroutine simply goes through the display lines one by one, displays
  2386. the line contents, and advances the line pointer.  To display a single line,
  2387. the line is fetched into the line buffer from far memory and the number of
  2388. displayable characters is calculated according to the line length and the
  2389. left-hand display margin.  The displayable characters (possibly zero) are
  2390. written to the screen memory and if the line isn't completely full, then the
  2391. remainder of the line is filled in with space characters.  The displaying is
  2392. completely performed by the "aceWinPut" system call.  One oddity that needs
  2393. to be handled is running out of document lines before filling the screen
  2394. range.  In this case, each remaining screen line is cleared.
  2395.  
  2396. Attributes (colors) are not used for this operation, since they are not
  2397. needed and using them would only slow us down.  They display-area color
  2398. cells are initialized when ZED starts (as are the status-line and
  2399. separator-line color cells) and don't change during operation.  The colors
  2400. come from the ACE palette (which the user can configure to his own liking).
  2401.  
  2402. This subroutine is used to both repaint the entire screen (when necessary)
  2403. and to repaint only one line or a few lines (when I can get away with
  2404. this).  Repainting takes time, so we want to repaint only what has changed.
  2405. However, repainting isn't too slow, especially when compared to serial-line
  2406. speeds, since screen updates are written directly to screen memory, although
  2407. the C64's soft-80 screen is significantly slower than the other screen types
  2408. since so much more processor work needs to be done just to make a single
  2409. character appear.
  2410.  
  2411. In the future, it may be useful to allow this function to abort in the
  2412. middle of this operation if the user presses a key before the repainting is
  2413. finished, in order to allow the user to work faster.  For example, if you
  2414. hold down the Page-Down keystroke, the speed that you go forward in the
  2415. document is limited by how fast the screen can be repainted.  If the repaint
  2416. operation were abortable, then you could always go forward as fast as the
  2417. key repeates, and when you get to where you are going and release the
  2418. Page-Down key, the screen would repaint one final time and everything would
  2419. be consistent.  A flag would need to be kept to tell whether the screen is
  2420. consistent or not, in order to make this work.
  2421.  
  2422. There is also a function that displays a message in the separator line on
  2423. the screen.  It also needs to store the displayed message in order to allow
  2424. the user to scroll through it if the screen is not wide enough to display it
  2425. in its entirety.  When the message is no longer needed, it is erased by
  2426. overwriting it with separator characters.  And, there is also a function
  2427. that updates all of the fields that have changed on the status line.
  2428.  
  2429. #(A)3.2: 3.2. MAIN CONTROL
  2430.  
  2431. Before I start talking about the implementations of the individual commands,
  2432. I should say something about the main control for the program.  After ZED
  2433. initializes and loads the initial document (even if you don't specify one,
  2434. ZED will default to the name "noname" and try to load it), control is passed
  2435. to a small main loop of simply displaying the cursor, waiting for a
  2436. keystroke, undisplaying the cursor, calling the subroutine associated with
  2437. the keystroke, and repeating.
  2438.  
  2439. #(A)3.3: 3.3. END UP, DOWN, LEFT, RIGHT
  2440.  
  2441. Moving the current line to the top and bottom of the document is straight
  2442. forward, because of the organization that was discussed in the data-
  2443. structure secion above.  To go to the top of the document, copy the
  2444. trailer-line pointer to the current line pointer and then fetch the next
  2445. pointer from the trailer line's header; this will give a pointer to the top
  2446. line.  Then we set the current line number to one and a couple of other
  2447. variables and call the subroutine discussed above to repaint the screen.
  2448.  
  2449. Going to the bottom of the document would be just as easy as going to the
  2450. top, except that we want the last line (the trailer line) to be displayed on
  2451. the bottom of the screen in order to present as much useful document content
  2452. to the user as possible.  If there are fewer lines in the file than will
  2453. fill a screen, then we cannot, of course, display an entire screen.
  2454.  
  2455. To make this business easier, a subroutine is provided that, given a
  2456. starting line pointer and a count, will scan until it either hits the
  2457. count-th line previous to the given one or it hits the top line of the
  2458. document.  It returns the number of lines that were actually scanned upwards
  2459. (possibly zero), the pointer to the line that it stopped scanning at, and a
  2460. flag indicating whether it stopped because it hit the top of the document or
  2461. not.  This subroutine is quite generally useful.  There is a similar
  2462. subroutine that scans downward.
  2463.  
  2464. So, after locating the bottom line of the document and setting the line
  2465. number, the scan-upwards subroutine is called to scan upwards the number of
  2466. displayable lines on the screen.  The screen is then repainted in its
  2467. entirety from the line that was scanned up to, and the new cursor-display
  2468. location is computed from the count of the lines that were scanned over.
  2469. This works equally well for a long document, a document shorter than the
  2470. height of the screen, and an empty document.
  2471.  
  2472. The End-Left and End-Right commands are very simple in that they don't even
  2473. have to change the current line pointer, but they do have to check if the
  2474. cursor has moved off either the left or right edge (margin) of the screen.
  2475. The visible columns go from the column number of the left margin, up to that
  2476. plus the width of the screen.  If the cursor goes off an edge of the screen,
  2477. then the new left margin will have to be computed and the entire display
  2478. will need to be repainted.
  2479.  
  2480. This repainting effectively achieves horizontal scrolling.  Lines in ZED, of
  2481. course, can be up to 240 characters across (241 if you count the carriage-
  2482. return character), but the widest screen that ACE supports is 80 columns.
  2483. Arguably, the horizontal scrolling could be done more efficiently by moving
  2484. the contents of the display left or right by the requred number of columns
  2485. and then filling in the opened spaces with the data from the correct columns
  2486. of the display lines in memory.  However, the additional complexity is
  2487. non-trivial and the speedup may not be all that great except for the soft-80
  2488. screen of the C64.  A better approach might be to go with the interruptable-
  2489. repainting idea that I spoke of earlier, if the current line were updated
  2490. first (so that you can see what you're doing) and the rest of the lines
  2491. afterwards.
  2492.  
  2493. #(A)3.4: 3.4. PAGE UP, DOWN, CURSOR UP, DOWN, LEFT, RIGHT, WORD LEFT & RIGHT
  2494.  
  2495. All of these functions follow quite naturally from what is above.  For Page-
  2496. Up and Down, the scan-up or scan-down subroutines already described are
  2497. called to find the new current line for the cursor and then the entire
  2498. screen is repainted, effectively paging up or down.
  2499.  
  2500. For cursor up and down, we just go up or down to the next line in the
  2501. document and adjust adjust the cursor location on the screen.  If the cursor
  2502. goes off the top or bottom of the screen, then we scroll the screen up or
  2503. down as appropriate (ACE can scroll the screen up or down and will
  2504. eventually be able to scroll it left and right (although this will be a bit
  2505. painful for the soft-80 screen since it may mean scrolling left and right
  2506. nybbles)).  Then, we display the current line at either the top or bottom of
  2507. the screen to fill in the blank line that we just opened up.  Because we use
  2508. scrolling and painting only a single line, we can scroll the screen fairly
  2509. quickly, easily keeping up with the cursor repeat rate, except on the
  2510. soft-80 screen.
  2511.  
  2512. For cursor left and right, we advance the cursor one position on the line
  2513. and see if it has gone over the edge.  If not, then we are done; nothing
  2514. needs to be redisplayed.  If we have gone off the edge, then we call the
  2515. cursor-up or cursor-down routines to go to the previous/next line and we
  2516. position the cursor to either the end or start of the new line.
  2517.  
  2518. The word left/right functions are similar to the cursor left/right
  2519. functions, except that we keep scanning until we run into the start of the
  2520. next word.  For word left, this is defined as running into a non-whitespace
  2521. character that is preceeded by a whitespace character.  A whitespace
  2522. character is defined as either a space, a TAB, a hard return, or the
  2523. beginning or ending of the document.  For word right, the start of the next
  2524. word is defined as a non-whitespace character that is preceeded by a
  2525. whitespace character, where we start searching from one position to the
  2526. right of the current cursor position.  If we run into the beginning or end
  2527. of the document, then we stop there.
  2528.  
  2529. BTW, all of these moving-around functions check the cursor position against
  2530. the display bounds and "scroll" the display left or right if the cursor has
  2531. gone off the screen.  Well, actually, there is one exception to this rule.
  2532. If the current line is the target-length number of characters long, and the
  2533. target length equals the screen width, and carriage returns are selected not
  2534. to be displayed, and the left margin of the display is column one
  2535. (external), and the cursor is in the target-length-plus-one position of the
  2536. line, then the screen is NOT scrolled right.  Instead, the cursor is
  2537. displayed on the last position of the line and is made to blink fast (an ACE
  2538. feature).  This is done to avoid the annoyance of having the screen scroll
  2539. right when you are editing a text file on, say, an 80-column screen that has
  2540. up to 80-character lines in it.  The standalone ACE does this too, when you
  2541. logically hit the 81st column.
  2542.  
  2543. #(A)4: 4. TEXT INPUT AND "SLOSHING"
  2544.  
  2545. So far, we can load up a document and whiz around inside of it, but we can't
  2546. actually change anything.  This section describes the single-character
  2547. modification operations of character input, rub, and delete, and the text
  2548. "sloshing" algorithm that is needed to make sure that lines are always as
  2549. full as they can be without going over the target length ("Come on down!").
  2550.  
  2551. #(A)4.1: 4.1. TEXT INPUT, DELETION
  2552.  
  2553. Adding a single character to a document isn't really very difficult. There
  2554. are two modes for single-character inputting: insert and overtype.  Insert
  2555. mode is generally more useful and more often used, but overtyping can be
  2556. very useful when dealing with tabular or specially formatted text.
  2557. Therefore, we must support both modes.  In some other text editors, overtype
  2558. mode is the natural mode because the cost of inserting a character can be
  2559. so high, but not here.
  2560.  
  2561. Actually, there isn't a whole lot of difference in the implementations of
  2562. the two modes.  For overtype mode, you just fetch the current line, take the
  2563. inputted character and store it into the line buffer at the current
  2564. position, stash the line back into memory, and repaint the line.  For insert
  2565. mode, we do the same thing, except that we copy the line from the cursor to
  2566. the end to one position beyond the cursor (backwards) and bump its length up
  2567. by one before storing the new character on the line.
  2568.  
  2569. Rubbing out a character (Commodore-DEL) is done in quite the same way,
  2570. except that we copy the rest of the line back one space and decrement the
  2571. length.  Oh, and when the length of the new line is different from the
  2572. length of the old line, we have to deallocate the old line and allocate new
  2573. memory for the new line, and surgically link it in with the rest of the
  2574. document.  I have a subroutine that does this.
  2575.  
  2576. The DEL key is handled as if you had typed Cursor Left then RUB, except when
  2577. you press DEL on the first column of a line and the previous line ends with
  2578. a hard return, the hard return of the previous line is removed instead.  I
  2579. decided to make the RUB (Co-DEL) key return an error instead of joining
  2580. lines together like DEL, because sometimes it is convenient to just lean on
  2581. the RUB key to delete to the end of a line.
  2582.  
  2583. #(A)4.2: 4.2. TEXT SLOSHING
  2584.  
  2585. But, we're not done with text modifications yet.  If we just left the
  2586. modifications as described in the previous sections, we would be end up with
  2587. lines that are longer than the target length, with ragged lines, and with
  2588. lines that don't join together like they should after pressing DEL in the
  2589. first column.
  2590.  
  2591. After each of the modifications, the text-sloshing routine is called to
  2592. straighten everything up and figure out how to redisplay the screen.  Often,
  2593. only one line needs to change, but sometimes, many lines or even the whole
  2594. screen will have to be updated, as sloshing text can continue for many lines
  2595. as line overflows and underflows cascade forward from the line that has just
  2596. been modified.  In fact, the text-sloshing routine is enormously complicated
  2597. and has many, many special cases. (Although, for all of its complexity, it
  2598. is only 400 lines long, although it still needs a few more features).
  2599.  
  2600. There are many more cases that could cause sloshing than you might think.
  2601. There are the obvious inserting/deleting one-too-many characters in the
  2602. current line, but there is also the case that an insertion or deletion
  2603. causes a space character to move to the right position on a line to allow
  2604. the line to be sloshed backward, or maybe you remove a space from the end of
  2605. a line that creates a word that would be too long to be contained on one
  2606. line and therefore needs to be sloshed forward.
  2607.  
  2608. The sloshing algorithm doesn't introduce or take away any characters from
  2609. the body of the document; it just reorganizes the existing characters.  All
  2610. of the spaces are retained at the ends of wrapped lines.  We don't want to
  2611. delete spaces, since it is difficult to reconstruct them, since two spaces
  2612. are normally between two sentences in text, but it is difficult for a
  2613. computer to figure out where a sentence ends.  In fact, keeping these spaces
  2614. can sometimes cause an anomaly: if all of the spaces won't fit on the end of
  2615. one line, then they will be displayed at the beginning of the next line.
  2616.  
  2617. The variables that are maintained by the algorithm are as follows:
  2618.  
  2619. sloshLinesAltered  = work2+0 ;(1) ;a simple count
  2620. sloshRedisplayAll  = work2+1 ;(1) ;$80=redisplay to bottom, $ff=force all
  2621. sloshRedisplayPrev = work2+2 ;(1) ;whether previous line needs to be repainted
  2622. sloshMaxChars      = work2+3 ;(1) ;number of chars that can be sloshed
  2623. sloshTailChar      = work2+4 ;(1) ;the last char of prev line
  2624. sloshTheCr         = work2+5 ;(1) ;whether a CR should be sloshed
  2625. sloshLinesInserted = work2+6 ;(1) ;number of new line records created
  2626. sloshLinesDeleted  = work2+7 ;(1) ;number of existing line records deleted
  2627. sloshCurAltered    = work2+8 ;(1) ;whether the current line has been altered
  2628. sloshTerminate     = work2+9 ;(1) ;flag to terminate (hit a hard return)
  2629. sloshCurTailChar   = work2+10 ;(1);last char of current line
  2630.  
  2631. The algorithm has a main loop that is repeated for each line that can be
  2632. sloshed.  The loop exits when we either run into a hard return or we run
  2633. into a line that does not need to be sloshed.  We start scanning from the
  2634. cursor line of the main document.
  2635.  
  2636. We first look at the previous line and see how many more characters it can
  2637. accommodate before being full.  Then, we scan the current line from this
  2638. point (the number of characters that could potentially be sloshed backwards)
  2639. back to the start of the line searching for spaces.  If there are no spaces,
  2640. then the current line cannot be sloshed back onto the previous line.  If we
  2641. do run into a space, then we stop searching and know that we can (and must)
  2642. slosh back the current line.  So, we remove the characters from the current
  2643. line and write it back (maintaining links as appropriate) and then go back
  2644. to the previous line and append these characters to it.
  2645.  
  2646. If the cursor happened to be on the line in a position that got sloshed
  2647. back, then we must adjust the cursor position and move it back to the
  2648. previous line.  If the previous line is before the start of the screen,
  2649. we must set the flag to redisplay the entire screen later.  If the current
  2650. line is the first line of the slosh area but the cursor didn't get moved
  2651. back to the previous line, then we must set the flag to indicate that
  2652. we must redisplay the previous line too when we repaint the screen.
  2653.  
  2654. If it turns out that we have sloshed back ALL of the characters on the
  2655. current line, then we must remove the empty line record of the current line
  2656. from the document and adjust the global line count.  We also have to worry
  2657. about sloshing back a hard return, and if we do, then we bail out of the
  2658. algorithm since we are done.  Oh, and we have to keep in mind whether we are
  2659. displaying carriage returns or not in calculating line lengths.
  2660.  
  2661. After shoshing backward, we check if the current line needs to be sloshed
  2662. forward.  It needs to be sloshed forward if it is either longer than the
  2663. target length or it ends in a non-space character and the first
  2664. word on the next line cannot be sloshed back.  The latter is a special case
  2665. and needs to be checked for specially, even thought the functionality
  2666. for doing so is redundant.
  2667.  
  2668. If we do need to slosh forward, we start scanning the current line at the
  2669. target-line-length point and scan backwards until we hit the first space.
  2670. If there is no space, then the current word is longer than the target length
  2671. and must remain abruptly broken over two (or more) lines.  We wrap it at the
  2672. target length.  If we do find a space earlier on the line, then we wrap the
  2673. line right after that space.  Oh, I forgot to mention: we need to do
  2674. something special for lines that end with non-spaces for backward sloshing
  2675. too.  If the previous line ends in a non-space (presumably because it
  2676. contains a single very long word), then we don't find any spaces to slosh
  2677. back to the end of the word, then we slosh back as many characters as will
  2678. fit, since the word is broken anyway, and we want it to have as many
  2679. characters as possible on a single line.
  2680.  
  2681. To wrap the line, we set the length of the current line to the new length
  2682. and replace the old version of the line in memory.  Then, we create a new
  2683. line record and store the characters that were wrapped in it and link this
  2684. line record in with the rest of the document.  And this is all that we do
  2685. here; we don't actually insert the wrapped characters into the next line,
  2686. since that would be more complicated, and since it might cause that line to
  2687. overflow.  If we just leave the wrapped characters, they will be joined with
  2688. the next line (if necessary) on the next iteration of the main sloshing loop
  2689. in a slosh-back operation.  We must adjust the cursor location, like before,
  2690. if the cursor was on the part of the line that got wrapped around.
  2691.  
  2692. At the end of a loop, we check to see if we have passed a hard return in
  2693. the document, in which case, we exit.  Otherwise, if either the current
  2694. line has been modified or if the current line is the first line to
  2695. be sloshed, then we go on to the next line and repeat the above
  2696. procedure.
  2697.  
  2698. On our way out, we do a little fine tuning of the "sloshLinesAltered",
  2699. "sloshRedisplayAll", and "sloshRedisplayPrev" variables, which were
  2700. described earlier.  These variables will be used to repaint the changed
  2701. portions of the screen display.  Part of the fine adjustment includes
  2702. comparing the number of lines that have been inserted and deleted from the
  2703. document.  If these two numbers match, then the bottom portion of the screen
  2704. doesn't have to be repainted, only the altered lines themselves; otherwise,
  2705. we need to repaint from the current line all the way to the bottom of the
  2706. screen.
  2707.  
  2708. The sloshing algorithm currently does not handle non-wrap mode; lines will
  2709. always be word wrapped.  Later, all lines will be broken at the N-th column
  2710. if you are not in word-wrap mode.  Also, the algorithm can produce an
  2711. anomalous wrapping in one case involving lines that end with non-spaces that
  2712. I can't seem to remember that this algorithm will fail in (but, the document
  2713. will still be interally consistent).  And finally, if you change the target
  2714. line length while editing a document (which you can't currently do), then
  2715. the algorithm may not be able to give optimal word wrapping in all cases
  2716. (though, again, the document will always be interally consistent).
  2717.  
  2718. #(A)5: 5. OTHER FEATURES
  2719.  
  2720. This secion discusses the other features of the editor that have not been
  2721. described yet.  In general, the operation of this version follows closely
  2722. from the standalone version, so you can read its documentation for more
  2723. details.  First, I will give a summary of all of the implemented and planned
  2724. commands, and then I will discuss the operation of a few selected commands.
  2725.  
  2726. #(A)5.1: 5.1. COMMAND SUMMARY
  2727.  
  2728. Here is a command summary.  The "I" column in this list tells whether the
  2729. feature is currently implemented or not.  A blank means "no", and an
  2730. asterisk means "yes".  Note that "currently" means "by the time that you
  2731. read this" (which will be a couple of weeks after I have written this).  The
  2732. "CODE" column tells the internal ACE-PETSCII code for the key.  A plus
  2733. symbol following it means that the shift status of the key is checked to
  2734. distinguish this key.  The "KEY" column tells what keystroke you must make
  2735. ("CT-" means Ctrl, "CO-" means Commodore, "SH-" means Shift, and "AL-" means
  2736. Alt).  The "ACTION" column tells you what happens.
  2737.  
  2738. I CODE  KEY      ACTION
  2739. - ----  -------  -------
  2740.   $e0   CT-@     Exchange cursor position with mark position
  2741. * $e1   CT-A     Alter case of letter under cursor
  2742.   $e2   CT-B     Go on to next document buffer
  2743.   $e2+  SH-CT-B  Go on to previous document buffer
  2744.   $e3   CT-C     Copy range
  2745. * $e4   CT-D     Delete range
  2746. * $e5   CT-E     Exit with save
  2747. * $e6   CT-F     Find next occurrence of hunt string
  2748.   $e6+  SH-CT-F  Find previous occurrence of hunt string
  2749.   $e7   CT-G     Go to given line number
  2750.   $e7+  SH-CT-G  Go to given _physical_ line number
  2751. * $e8   CT-H     Set Hunt string
  2752. * $e9   CT-I     Insert new file into current one
  2753.   $ea   CT-J     Juggle the lines of paragraphs, keep separate
  2754.   $eb   CT-K     Kill current line
  2755. * $ec   CT-L     Load file
  2756.   $ed   CT-M     Set Mark for range operations
  2757. * $ee   CT-N     Set Name of current file
  2758.   $ef   CT-O     Set Options: input/output translation/tab-expansion, etc.
  2759.   $f0   CT-P     Print current file
  2760. * $f1   CT-Q     Quit without save
  2761. * $f2   CT-R     Recall text from the Kill buffer
  2762. * $f2+  SH-CT-R  Recall text from the Rub buffer
  2763. * $f3   CT-S     Save file
  2764.   $f4   CT-T     Tie together multiple lines into one big line (paragraph)
  2765.   $f5   CT-U     Undo the last change made to the document
  2766.   $f6   CT-V     Verify file
  2767.   $f7   CT-W     Write range with new name
  2768.   $f8   CT-X     Extract the individual lines from a paragraph
  2769.   $f9   CT-Y     Replace (all the other letters were taken!)
  2770. * $fa   CT-Z     Goto bottom of screen
  2771. * $fb   CT-[     Toggle insert mode
  2772. * $fc   CT-\     Toggle modified flag
  2773. * $fd   CT-]     Toggle indent mode
  2774.   $fe   CT-^     Change the current working directory
  2775.   $ff   CT-_     Compose ISO-8859-1 character
  2776.  
  2777. I CODE  KEY          ACTION
  2778. - ----  ---          ------
  2779. * $91   UP           Cursor up
  2780. * $11   DOWN         Cursor down
  2781. * $9d   LEFT         Cursor left
  2782. * $1d   RIGHT        Cursor right
  2783. * $06   SH-LEFT      Word left
  2784. * $0b   SH-RIGHT     Word right
  2785. * $16   CT-UP        Page up
  2786. * $17   CT-DOWN      Page down
  2787. * $19   CT-LEFT      Page left
  2788. * $1a   CT-RIGHT     Page right
  2789. * $0c   CO-UP        Goto top of document
  2790. * $0f   CO-DOWN      Goto bottom of document
  2791. * $10   CO-LEFT      Goto beginning of line
  2792. * $15   CO-RIGHT     Goto end of line
  2793.  
  2794. * $0d   RETURN       Split current line (indent not yet implemented)
  2795.   $8d   SH-RETURN    Go to next paragraph
  2796.   $01   CT-RETURN    Go up one paragraph
  2797.   $09   TAB          Tab
  2798.   $02   SH-TAB       Backtab
  2799.   $18   CT-TAB       Insert to next tab stop
  2800. * $14   DEL          Delete character
  2801. * $08   CO-DEL       Rubout
  2802. * $94   INST         Insert one space
  2803. * $13   HOME         <nothing>
  2804. * $93   CLR          Cursor home
  2805.   $04   HELP         Bring up help window
  2806.   $84   SH-HELP      Display help screen
  2807. * $0a   LINEFEED     <nothing>
  2808. * $07   SH-LINEFEED  <nothing>
  2809. * $1b   ESCAPE       Redisplay screen
  2810. * $0e   SH-ESCAPE    <nothing>
  2811. * $03   STOP         <stop some operations>
  2812. * $83   RUN          <nothing>
  2813.  
  2814.   $90   CT-1         Clear document
  2815.   $05   CT-2         Clear buffer
  2816.   $1c   CT-3         Enter hexadecimal PETSCII character code
  2817.   $9f   CT-4         Display directory
  2818.   $9c   CT-5         Destroy current document buffer
  2819.   $1e   CT-6         Create new document buffer
  2820.   $1f   CT-7         Display PETSCII code of current character
  2821. * $9e   CT-8         Scroll left margin of status line
  2822. * $12   CT-9         Reverse screen on
  2823. * $92   CT-0         Screen reverse off
  2824.  
  2825.   $81   CO-1         Set display to show single buffer
  2826.   $95   CO-2         Set display to show two buffers
  2827.   $96   CO-3         Set display to show three buffers
  2828.   $97   CO-4         Set display to 40 columns, default rows
  2829.   $98   CO-5         Set display to take full screen
  2830.   $99   CO-6         Set display to default number of rows
  2831.   $9a   CO-7         Set display to maximum number of rows
  2832.   $9b   CO-8         Set display to 80 columns, default rows
  2833.  
  2834.   $85   F1           Function key 1  : user-defined string
  2835.   $89   SH-F1        Function key 2  : user-defined string
  2836.   $86   F3           Function key 3  : user-defined string
  2837.   $8a   SH-F3        Function key 4  : user-defined string
  2838.   $87   F5           Function key 5  : user-defined string
  2839.   $8b   SH-F5        Function key 6  : user-defined string
  2840.   $88   F7           Function key 7  : user-defined string
  2841.   $8c   SH-F7        Function key 8  : user-defined string
  2842.   $80   CT-F1        Function key 9  : user-defined string
  2843.   $82   CT-F3        Function key 10 : user-defined string
  2844.   $8e   CT-F5        Function key 11 : user-defined string
  2845.   $8f   CT-F7        Function key 12 : user-defined string
  2846.  
  2847. #(A)5.2: 5.2. TEXT SAVE
  2848.  
  2849. This function is, of course, implemented, since the text-modification
  2850. functions of the editor would be useless without it.  It is really quite
  2851. simple, because of the data structure of the document.  First, we try to
  2852. open the file for writing.  If not successful and we get a "file exists"
  2853. error, then we scratch the old file.  Then, we re-open for writing.
  2854.  
  2855. To save the file contents, we start at the top line, and fetch each line in
  2856. turn until we hit the trailer line of the document, at which point we are
  2857. finished.  After fetching the line, we check if it ends with a hard return,
  2858. and if so, we append the line buffer with a carriage return character and
  2859. bump up the line length.  We then call the ACE "write" primitive with the
  2860. line buffer as the argument to write out the line.  Writing in this size of
  2861. chunk rather than in single bytes gives ACE the opportunity to carry out
  2862. this operation as efficiently as it can.
  2863.  
  2864. We then close the file and we are done.  We display status information to
  2865. the user during all phases of this operation, and we certainly tell him if
  2866. anything goes wrong.
  2867.  
  2868. #(A)5.3: 5.3. RANGE DELETION & RECALL
  2869.  
  2870. Range delete and recall are implemented, since they are very useful for
  2871. general editing.  What will normally happen is that the user will set the
  2872. mark with Ctrl-M (mark) to one end of the range to be deleted, and then move
  2873. the cursor to the other end of the range and press Ctrl-D (delete).  The
  2874. text then disappears into the kill buffer and can be recalled any number of
  2875. times at any point in the document using the Ctrl-R (recall).
  2876.  
  2877. One difference between this ZED and the operations mentioned here are
  2878. "character oriented" rather than "line oriented".  So, you can now delete
  2879. only portions of lines rather than entire lines.  You just have to keep in
  2880. mind that the cursor is logically located "between" the previous character
  2881. and the character that the cursor is currently over.  For example, if the
  2882. cursor was on the "y" in "xyz", then the mark would be set to between the
  2883. "x" and "y" if you pressed Ctrl-M at that point.  This also means that if
  2884. you wanted to delete an entire line (that ended with a hard return), then
  2885. you would move the cursor to the first character of the line and press
  2886. Ctrl-M and then move the cursor to the first character of the NEXT line and
  2887. press Ctrl-D.  (The Hard Return itself won't be included in the delete
  2888. operation if you move the cursor to the end of the line to be deleted--this
  2889. is one of the reasons for having a displayable trailer line).
  2890.  
  2891. To implement the delete operation, all of the lines in the operation are
  2892. unlinked from the main document and are linked into the kill buffer.  If
  2893. there already was something in the kill buffer, then it is deallocated and
  2894. the kill buffer is cleared.  A trailer line is permanently allocated to the
  2895. kill buffer, to make it work consistently with the main document.  Partial
  2896. lines (potentially, the first and last lines of the range) are a bit of a
  2897. pain and have to be split into two lines at the point of the mark/cursor,
  2898. where one of the broken lines stays with the document and the other goes
  2899. into the kill buffer.  After extracting the range, the lines around the
  2900. extracted region are sewn back together ("sponge, nurse!") and text is
  2901. "sloshed" about the stitch point (if necessary).  The number of bytes and
  2902. lines involved are counted up and are subtracted from the global counts
  2903. for the main document.
  2904.  
  2905. Ctrl-C (copy) is very similar to the delete operation, except that the data
  2906. to be deleted is actually copied to the kill buffer and the document is left
  2907. unmodified.  Range copy is not currently implemented, since its operation
  2908. can be emulated with a Ctrl-D followed immediately by a Ctrl-R.
  2909.  
  2910. To implement the recall operation, the kill buffer is replicated into a
  2911. temporary document and the current line of the main document is broken into
  2912. two lines at the recall point (if necessary).  Then, the temporary document
  2913. is linked into the main document at the recall point and the text is
  2914. "sloshed" about the two stitch points.  The line and byte counts are
  2915. adjusted, and we are done.
  2916.  
  2917. #(A)5.4: 5.4. TEXT SEARCHING
  2918.  
  2919. Forward text searching is implemented, since it is very useful for both
  2920. finding things and for moving quickly around in a document.  (Reverse search
  2921. and Range search and replace are not currently implemented, since they are
  2922. less useful).
  2923.  
  2924. The implementation is quite straightforward.  The user will first use Ctrl-H
  2925. (hunt-string) to set the string to search for.  The user will input this on
  2926. the top line of the screen, and we don't have to do much work for inputting
  2927. the string, since ACE already provides a console-input routine complete with
  2928. left/right cursor movement and a scroll-back buffer (although it is a bit
  2929. hard to use if the input line is longer than the input window on the
  2930. screen).
  2931.  
  2932. After the search string is set, the user will press Ctrl-F (find) to find
  2933. the next occurrence of the string.  So, we just search for that string,
  2934. starting at the cursor position to the right of the current position.  A
  2935. simple algorithm of keeping a pointer to the current scan position in the
  2936. hunt string and pointers to both the current position in the document and to
  2937. the position in the document corresponding to the start of the string is
  2938. used.
  2939.  
  2940. If the current document character matches the current hunt-string character,
  2941. then both the document and hunt-string pointers are advanced.  If the hunt
  2942. string is exhausted by this, then we have found a match and can stop
  2943. searching.  We move the cursor to the saved document position of the start
  2944. of the hunt string and exit.  If the characters don't match, then we move
  2945. the current document pointer back to the postition corresponding to the
  2946. start of the hunt string, advance it by one, save it, and start searching
  2947. again.  Our algorithm needs to be able to wrap around soft returns in the
  2948. main document.
  2949.  
  2950. #(A)6: 6. CONCLUSION
  2951.  
  2952. So, here we finally have the basic ACE version of the ZED text editor that I
  2953. have been promising for a very long time.  The new version doesn't contain
  2954. all of the features of the standalone version, but I am working on it.  The
  2955. new version does, however, include a few features that the old version does
  2956. not, like long lines, horizontal scrolling, text "sloshing", the ability to
  2957. use additional memory types for storage, the ability to work on the C64,
  2958. integration with a command-line environment, and full assembler-code
  2959. availability (Real Soon Now(TM)).
  2960.  
  2961. In order to make ZED operational as a word processor, some means of giving
  2962. embedded commands and for formatting and printing these commands must be
  2963. provided.  I was originally thinking that an EasyScript or SpeedScript kind
  2964. of embedded-command structure, and then I was thinking abouta LaTeX kind of
  2965. structure (the LaTeX structure is superior), but I am now thinking that an
  2966. HTML type of format-command structure might be rather apropos.  Why then I
  2967. would need to create a print formatter and previewer that might be usable
  2968. for other purposes, too.
  2969.  
  2970. ============================================================================
  2971.  
  2972. #(@)trivia: Commodore Trivia
  2973.             by Jim Brain (brain@mail.msen.com)
  2974.           
  2975. #(A): Introduction
  2976.  
  2977. Well, the cold has moved in on us in Michigan, but the Commodore information
  2978. coming into the house is keeping us warm.  Some orphan computers have showed
  2979. up, including a Commodore 65 and C116, as well as a couple of Commodore B-128
  2980. computers with all the fixin's.  So, armed with the hardware, I have come up
  2981. with some brain ticklers for the Commodore know-it-all.
  2982.  
  2983. As some may know, these questions are part of a contest held each month on
  2984. the Internet, in which the winner receives a donated prize.  I encourage
  2985. those who can received the newest editions of trivia to enter the contest.
  2986.  
  2987. This article contains the questions and answers for trivia editions #19-22,
  2988. with questions for the current contest, #23.  
  2989.  
  2990. If you wish, you can subscribe to the trivia mailing list and receive the
  2991. newest editions of the trivia via Internet email.  To add your name to the
  2992. list, please mail a message:
  2993.    
  2994. To: brain@mail.msen.com
  2995. Subject: MAILSERV
  2996. Body:
  2997. subscribe trivia Firstname Lastname
  2998. help
  2999. quit
  3000.    
  3001. #(A): Trivia Questions
  3002.  
  3003. Q $120) What is the model number of the assembler/monitor for the KIM-1?
  3004.  
  3005. A $120) The KIM-5 was the model number of the editor/assembler product.
  3006.  
  3007. Q $121) How many LEDs are on the KIM-1?
  3008.  
  3009. A $121) The basic unit contains 6 7-segment LED displays, or 42 LEDs if
  3010.         you count each LED in a segment.
  3011.  
  3012. Q $122) What is the model number of the REC chip used in the REU?
  3013.  
  3014. A $122) MOS 8726.
  3015.  
  3016. Q $123) At least two versions of the above chip exist.  What is the main
  3017.         physical difference between the versions?
  3018.  
  3019. A $123) The eraly versio of the chip (8726-R1) exists in DIP form, while the
  3020.         8726-r4-r8 exists as a "J-lead" square surface mount unit.
  3021.  
  3022. Q $124) Why couldn't regular Atari(tm) style joystcks be used with the
  3023.         Commodore Plus/4 series?
  3024.  
  3025. A $124) Instead of using the de-facto 9 pin D-subminuture connector for the
  3026.         joysticks, the Plus/4 series used small mini-DIN connectors.  Some
  3027.         sources claim the older connectors were leaking a fair bit of
  3028.         radio interference and were preventing the units from attaining
  3029.         FCC approval, so the connectors were changed to the better-shielded
  3030.         mini-DIN types.
  3031.  
  3032. Q $125) What was the first joystick model Commodore produced that would
  3033.         function with the Plus/4 computer line?
  3034.  
  3035. A $125) The Commodore T-1341 Joystick, which had the special mini-DIN 
  3036.         connector
  3037.  
  3038. Q $126) How many computer models are included in the Plus/4 line?
  3039.  
  3040. A $126) At last count, 3 models in the Plus/4 series were produced:
  3041.  
  3042.         The Commodore Plus/4
  3043.         The Commodore 16
  3044.         The Commodore 116
  3045.  
  3046.         Some Commodore 264 models are known to exist, but are not counted, 
  3047.         since the 264 was the prototype model of the Plus/4.  Also, a V364
  3048.         model was planned, but only one unit is known to exist.
  3049.  
  3050. Q $127) In a normal Commodore disk drive Directory Entry, what relative
  3051.         offset denotes the start of the program name?
  3052.  
  3053. A $127) The filename starts at the 4th byte in the directory entry.
  3054.  
  3055. Q $128) How many tracks in a 1541 or 4040 are normally available for use as
  3056.         storage?
  3057.  
  3058. A $128) 35 tracks.
  3059.  
  3060. Q $129) How many bytes comprise a single disk drive directory entry?
  3061.  
  3062. A $129) 30 bytes.  
  3063.  
  3064. Q $12A) What is the model number of the Commodore dual drive with a total
  3065.         capacity per unit of 2.12MB?
  3066.  
  3067. A $12A) The Commodore 8250 or 8250LP dual disk drive.
  3068.  
  3069. Q $12B) On the drive denoted in $12A, how large could a single sequential
  3070.         file be?
  3071.  
  3072. A $12B) 1.025 megabytes.
  3073.  
  3074. Q $12C) At least two version of the Commodore 64C keyboard exist.  What is
  3075.         the difference between them?  Extra Credit: Why?
  3076.  
  3077. A $12C) One one keyboard style, the Commodore graphics are printed on the
  3078.         front of the keys, while they appear above the letters on the keys
  3079.         in the second type of keyboard.  I can't answer the extra credit
  3080.         part except to say that Commodore was always seeking the best deal.
  3081.         aybe a new keyboard manufacturer got the bid and changed the layout.
  3082.  
  3083. Q $12D) On the Commodore 64, what area of memory is swapped out when using an
  3084.         REU with RamDos?
  3085.  
  3086. A $12D) $6000 - $7fff is swapped out when a RAMDOS command is executing.
  3087.  
  3088. Q $12E) Commodore manufactured two different versions of the 1541-II drive.  
  3089.         What is the difference between them?
  3090.  
  3091. A $12E) The drive mechanisms differ in the two drives.  You can tell which you
  3092.         have by the appearance of the front of the drive.  If the lever hits
  3093.         a rest in the release position, you have the direct drive model.  If 
  3094.         the lever has no such rest visible, the drive cotains the belt drive
  3095.         mechanism.
  3096.  
  3097. Q $12F) How many colors could the Commodore 1520 plotter plot in?
  3098.  
  3099. A $12F) 4.  red, black, blue, and green.
  3100.  
  3101. Q $130) The Commodore Plus/4 was referred to as the "___________ Machine".
  3102.  
  3103. A $130) Productivity.
  3104.  
  3105. Q $131) Although the Commodore 16 and 116 were functionally equivalent, what
  3106.         two physical characteristics distinguished one from another?
  3107.  
  3108. A $131) Case style and keyboard.  The C16 is enclosed in a VIC20/C64 style
  3109.         case with keyboard, while the C116 sports a scaled down Plus/4
  3110.         style case and "chicklet" keyboard.
  3111.  
  3112. Q $132) How many pins are there on the Commodore plus/4 expansion port
  3113.         connector?
  3114.  
  3115. A $132) 50 pins.
  3116.  
  3117. Q $133) On which side of the Commodore 65 (as it is facing you) did Commodore
  3118.         place the power switch on?
  3119.  
  3120. A $133) The left side.  Since the disk drive fills the entire right side, the
  3121.         left side is an obvious choice, as the swith would require cabling if
  3122.         installed on the right side.
  3123.  
  3124. Q $134) How many keys are on a standard Commodore 128 keyboard?
  3125.  
  3126. A $134) 92 keys.
  3127.  
  3128. Q $135) What color are the drive LEDs on the SX64 drive?
  3129.  
  3130. A $135) There is only one LED, a red in-use LED.
  3131.  
  3132. Q $136) True or False?  The Commodore 64 and VIC-20 keyboards are
  3133.         interchangeable.
  3134.  
  3135. A $136) True.
  3136.  
  3137. Q $137) On a 1526/MPS 802 printer, how many redefinable characters
  3138.         were available for use per line of text?
  3139.  
  3140. A $137) 1.  True fact:  In order to print a line of graphics, one must
  3141.         print a GFX char, do a returb without linefeed (resets the graphic
  3142.         character, evidently), the tab over and repeat the cycle until 80
  3143.         characters were printed.  I had one, and it took me 7 hours to 
  3144.         print 21 pages of GEOWrite text!
  3145.  
  3146. Q $138) To set up a redefinable character on the MPS 802/1526 printer, what
  3147.         secondary address must be opened?
  3148.  
  3149. A $138) Secondary address #5.
  3150.  
  3151. Q $139) How many pins are in each Euro-DIN plug used on the Plus/4-C16
  3152.         joysticks?
  3153.  
  3154. A $139) 8 pins.
  3155.  
  3156. Q $13A) How many pins are on a regular Commodore VIC-20/C64 joystick
  3157.         connector?
  3158.  
  3159. A $13A) 9 pins.
  3160.  
  3161. Q $13B) What BASIC command is used to change from C128 mode to C64 mode on a 
  3162.         C128?
  3163.  
  3164. A $13B) go 64.  It will ask for confirmation.
  3165.  
  3166. Q $13C) What were the four integrated programs included in the infamous
  3167.         "3+1" software in the Plus/4?
  3168.  
  3169. A $13C) A word processor, spreadsheet, graphics software, and a data management
  3170.         program.
  3171.  
  3172. Q $13D) Which Commodore serial printer(s) had a small switch that allowed it
  3173.         to be addressed as either device 4 or device 5?
  3174.  
  3175. A $13D) The 1525, MPS 801, and MPS 803 had such a switch.  Although I cannot 
  3176.         confirm this, I believe the 1515, the precursor to the 1525, also 
  3177.         had the 4/5 switch.
  3178.  
  3179. Q $13E) How many addressable registers does the Commodore VIC-II IC have?
  3180.  
  3181. A $13E) There are 47 control registers in the Commodore VIC-II chip.
  3182.  
  3183. Q $13F) On a Commodore PET machine, what output appears on the screen after
  3184.         typing in SAVE "",2?
  3185.  
  3186. A $13F) PRESS PLAY AND RECORD ON TAPE #2
  3187.  
  3188. Q $140) What was the model number of the microprocessor used in the
  3189.         first of the Commodore 264 Series?
  3190.  
  3191. A $140) The early Plus/4 units contained a 7501 microprocessor, and the
  3192.         later units featured a 8501 microprocessor.  The only differences
  3193.         between the two units is the manufacturing process and die size.
  3194.  
  3195. Q $141) How fast could the microprocessor in the Commodore 264 Series
  3196.         theoretically run at?
  3197.  
  3198. A $141) 1.76 MHz.
  3199.  
  3200. Q $142) How many colors can a Commodore Plus/4 display at once?
  3201.  
  3202. A $142) 8 shades each of 16 colors, but the 8 shades of black are still
  3203.         still black, so a total of 121 colors are possible.
  3204.  
  3205. Q $143) What anomaly exists in the numbering of the BASIC interpreter
  3206.         in the Plus/4 as 3.5?
  3207.  
  3208. A $143) This version contained almost all of the commands in Version 4.0, 
  3209.         plus some new commands for graphics and sound.
  3210.  
  3211. Q $144) After the very first 1581 disk drives were introduced, Commodore
  3212.         found that the WD1770 disk controller chip in the drive could corrupt
  3213.         the disk in some situations.  So, Commodore offered a replacement
  3214.         IC to fix the problem.  What was the number of the replacement IC?
  3215.  
  3216. A $144) The Western Digital WD1772 IC.
  3217.  
  3218. Q $145) On some very early CBM 1541 drives, what would happen if the serial
  3219.         bus CLOCK and DATA lines were high upon startup?
  3220.  
  3221. A $145) On the very first 1541 drives (I suspect the feature was also on the
  3222.         1540 as well), On power-up, the drive would jump to a subroutine at
  3223.         $E780 after performing the reset routine.  The code there would check
  3224.         for the high state of CLOCK and DATA.  If found, the code would wait
  3225.         until both go low and then store '*' into the filename buffer, sets the
  3226.         filename length to 1, and then jumps to the & command, which loads
  3227.         a USR file and executes it.
  3228.  
  3229.         Since the Commodore computer never used this feature, and some machines
  3230.         would boot with these lines randomly high, Commodore removed the
  3231.         feature.
  3232.  
  3233. Q $146) In question $0F8, we learned that one must DIMension an array in
  3234.         BASIC if it will have more than 11 elements.  Which Commodore
  3235.         produced reference book ncorrectly claims the need to DIMension 
  3236.         arrays for more than 10 elements.
  3237.  
  3238. A $146) The Commodore 128 Programmer's Reference Guide.  Page 17.
  3239.  
  3240. Q $147) Why should serial device number 31 not be used? 
  3241.  
  3242. A $147) While it is specified as a valid serial bus address, when "or"ed with
  3243.         certain commands, it results in a bad command, hanging the bus and
  3244.         the serial drivers.
  3245.  
  3246. Q $148) On most VIC game cartridges from VIC-1910 up, toggling interlaced
  3247.         screen display can be done with a keypress.  Which key?
  3248.  
  3249. A $148) Press the F7 function key.
  3250.  
  3251. Q $149) Which cartidge fitting the criteria in $148 does not toggle interlace
  3252.         display with the same keypress as the others?  How is it toggled
  3253.         on this cartridge?
  3254.  
  3255. A $149) Gorf, VIC-1923.  Pushing the joystick up toggles interlace mode.
  3256.  
  3257. Q $14A) The Commodore 64 KERNAL and BASIC code use every opcode in the 6510
  3258.         CPU except three.  Which three?
  3259.  
  3260. A $14A) BRK, CLV, and SED.
  3261.  
  3262. Q $14B) For what purpose does the BASIC interpreter in a Commodore 64 
  3263.         require the Complex Interface Adaptor (CIA) IC? 
  3264.  
  3265. A $14B) In order to calculate random values for the BASIC function RND(0),
  3266.         the first 4 registers of the CIA whose address is provided by the
  3267.         IOBASE KERNAL routine are read.
  3268.  
  3269. Q $14C) On the Commodore 128, the 80 column output is output by the VDC
  3270.         chip.  What does VDC stand for?
  3271.  
  3272. A $14C) Video Display Controller.
  3273.  
  3274. Q $14D) By now, most people know about the ill-fated Commodore 65.  What
  3275.         were the specifications on the original Commodore 65 idea?
  3276.  
  3277. A $14D) A Commodore C64C with a built-in 1581.
  3278.  
  3279. Q $14E) When referring to the Commodore 4032, one usually states that
  3280.         one has a "thin 40" or a "fat 40".  What does "thin" and "fat"
  3281.         signify?
  3282.  
  3283. A $14E) A "thin 40" had a 9" screen and could not be upgraded.  The
  3284.         "fat 40" had a 12" screen, and could be upgraded to a 8000 series
  3285.         machine with some upgrade chips.
  3286.  
  3287. Q $14F) If you own a Commodore 4032, how can you tell which kind (thin
  3288.         or fat) you have?
  3289.  
  3290. A $14F) If you hold down the cursor key and it repeats, you have a "fat 40".
  3291.         (Of course, inspection could also be used, as the "thin" unit had a
  3292.          smaller screen)
  3293.  
  3294. Q $150) How nmany keys are on a standard Commodore B-128 keyboard?
  3295.  
  3296. A $150) 94 keys.
  3297.  
  3298. Q $151) How many revisions of the 1541 printed circuit board are
  3299.         known to exist?
  3300.  
  3301. A $151) For the 1541:
  3302.  
  3303.         PCB# 1540001    The "long board", as used in the 1540.
  3304.         PCB# 1540008-01 Minor revisions to the 1540001 board.
  3305.         PCB# 1540048    The "short board".
  3306.         PCB# 1540050    Minor revisions to the 1540048 board.
  3307.                         -01   ALPS mechanism
  3308.                         -03   Newtronics mechanism
  3309.         PCB# 250442-01  A revision of the short board. 1541 A board
  3310.         PCB# 250446-01  Minor revisions to the #250442 board, 1541 A-2 board
  3311.         PCB# 250446-03  Cost reduced 250442-03 board.  the 1541A C/R.
  3312.         
  3313.         For the 1541C:
  3314.  
  3315.         PCB# 250448-01  Contains the track 1 sensor logic.  the 1541B board.
  3316.         
  3317.         For the 1541-II:
  3318.         
  3319.         PCB# 340503     Cost reduced board. Termed the 1541-II board. 
  3320.         
  3321.         There might be others, but these we can confirm.  There are 9
  3322.         if you count the 1541-II board as a 1541 board, 8 if not.
  3323.  
  3324. Q $152) The Commodore 6510 CPU has two internal I/O registers.  Where in the
  3325.         Commodore 64 are these two registers located at?
  3326.  
  3327. A $152) Location $0000 and $0001
  3328.  
  3329. Q $153) The Commodore 64 cotains 64kB of memory.  How many bytes is in
  3330.         64kB?
  3331.  
  3332. A $153) 65536 bytes
  3333.  
  3334. Q $154) What is the name of the Commodore employee responsible for much of
  3335.         the Commodore 128 and 65 software development, among other 
  3336.         accomplishments?  (hint: initials are FB)
  3337.  
  3338. A $154) Fred Bowen.
  3339.  
  3340. Q $155) In question $13F, we found out the message that was displayed after
  3341.         typing SAVE "",2.  Why did Commodore change that message on the
  3342.         VIC-20?
  3343.  
  3344. A $155) The original message, as detailed in Q $13F was:
  3345.  
  3346.         PRESS PLAY AND RECORD ON TAPE #2
  3347.  
  3348.         Commodore found that people were pressing the play buttopn BEFORE the
  3349.         record button, which would prevent the record button from functioning
  3350.         in some cases.  So, Commodore changed the message to:
  3351.  
  3352.         PRESS RECORD AND PLAY ON TAPE
  3353.  
  3354.         To circumvent the problem.  Note that the VIC did not have 2 tape
  3355.         interfaces, so no cassette number was needed.
  3356.  
  3357. Q $156) What was the number of Commodore 64 machines sold, within 4 million?
  3358.  
  3359. A $156) 17 million  (This information came from Dave Haynie)
  3360.  
  3361. Q $157) What was the number of Commodore 128 machines sold, within 1 million?
  3362.  
  3363. A $157) 4.5 million (This information came from Dave Haynie)
  3364.  
  3365. Q $158) In 1985, Commodore previewed the Commodore LCD Laptop computer at the
  3366.         January CES show.  How many software packages were to be built-in?
  3367.  
  3368. A $158) 8:
  3369.         
  3370.         Word Processor
  3371.         File Manager
  3372.         Spreadsheet
  3373.         Address Book
  3374.         Scheduler
  3375.         Calculator
  3376.         Memo Pad
  3377.         Telecommunications Package
  3378.  
  3379. Q $159) In the Commodore LCD unit, what were the text screen dimensions?
  3380.  
  3381. A $159) 80 coumns by 16 rows.  1200 characters on screen.
  3382.  
  3383. Q $15A) What is the version number of the only known "bug-free" VIC-II
  3384.         IC?
  3385.  
  3386. A $15A) 6569-R5.  What's funny is that this chip was manufactured after
  3387.         the Commodore 128 was introduced, so they used the 6569-R3 for the
  3388.         development of the Vic-IIe chip (8563 series), which is buggy.
  3389.         So, the newest PAL 64s have a better VIC than the C128.
  3390.  
  3391. Q $15B) Machine language programmer typically use the .X register to index 
  3392.         into small arrays.  What is the largest byte-array size that can be
  3393.         handled in this way?
  3394.  
  3395. A $15B) 256 bytes.
  3396.  
  3397. Q $15C) In the mid-1980's, Commodore started manufacturing IBM clone PCs.
  3398.         One of the models had a name which was a type of horse.  Name the term.
  3399.  
  3400. A $15C) The Commodore "Colt" PC.
  3401.  
  3402. Q $15D) What is the model number of the first mouse introduced for the
  3403.         Commodore 64?
  3404.  
  3405. A $15D) The 1350.  
  3406.  
  3407. Q $15E) What was the problem with the mouse in question $15D?
  3408.  
  3409. A $15E) As Commodore was either still developing the (now more 
  3410.         popular) 1351 mouse or the 1350 was designed as a lower cost 
  3411.         alternative, this mouse could only emulate a joystick.  When you
  3412.         rolled it up, the joystick "UP" pin was triggered.  Likewise for the
  3413.         other directions.
  3414.  
  3415. Q $15F) If you hold down the cursor key on the CBM 4000 series machine and it
  3416.         does not repeat, what fact about the machine do you now know?
  3417.         (other than the key doesn't repeat)
  3418.  
  3419. A $15F) It is a thin 40XX machine, meaning it could not be upgraded to an
  3420.         80XX machine via chip swaps.
  3421.  
  3422. ------- A publication describing BASIC on the Commodore makes the claim that
  3423.         BASIC variables are limited to 5 characters, with the first two being
  3424.         significant.  The example to prove this point in the book is given as:
  3425.  
  3426.         ABCDE=5   works, while
  3427.         ABCDEF=6  does not.
  3428.  
  3429.         The following questions refer to this claim:
  3430.  
  3431. Q $160) What is wrong with the above statement?
  3432.  
  3433. Q $161) What causes the variable ABCDEF to fail?
  3434.  
  3435. Q $162) How long can variable names really be?
  3436.  
  3437.         Extra Credit:  Who was the book publisher?
  3438.  
  3439. ------- The Commodore LCD Computer system, much like the Commodore 65,
  3440.         was a product that never reached the market.  Do you remember this
  3441.         pint-size CBM machine?
  3442.  
  3443. Q $163) How many keys were on the CLCD keyboard?
  3444.  
  3445. Q $164) What does LCD in the Commodore LCD stand for?
  3446.  
  3447. Q $165) Was an internal modem to be includes?
  3448.  
  3449. Q $166) Like the Plus/4 the CLCD unit had integrated software.  What programs
  3450.         were included?
  3451.  
  3452. Q $167) How many batteries of what type did the CLCD use for power?
  3453.  
  3454. Q $168) Approximately how much did the CLCD unit weigh?
  3455.  
  3456. Q $169) What version of BASIC was to be included with the CLCD computer?
  3457.  
  3458. Q $16A) The CLCD unit contained a port that could be used with a 
  3459.         Hewlett-Packard device.  What did the device do?
  3460.  
  3461. Q $16B) What microprocessor did the CLCD unit utilize?
  3462.  
  3463. Q $16C) In addition to the usual inclusion of standard Commodore ports,
  3464.         what two industry standard ports were included on the CLCD?
  3465.  
  3466. Q $16D) How much RAM did the CLCD computer include?
  3467.  
  3468. Q $16E) How many pixels are on the LCD screen on the CLCD machine?
  3469.  
  3470. Q $16F) How much ROM did the CLCD computer contain?
  3471.  
  3472. ============================================================================
  3473.  
  3474. #(@)gfx: Hacking Graphics: Let's Get Graphical
  3475.             by Rick Mosdell (rick.mosdell@canrem.com)
  3476.  
  3477. (c) September 1995 (used by permission)
  3478.  
  3479. #(A): Introduction
  3480.  
  3481. High resolution graphics on the C64 is not all that complicated. How to set 
  3482. up the VIC-chip to see your bitmap and colors IS, so this will not become 
  3483. a discussion on which bits to flip or where to put your blocks of data 
  3484. inside a computer already renowned for its lack of space. Instead, I 
  3485. am interested in the internal data formats of the only two graphics formats. 
  3486.  
  3487. #(A): Definitions
  3488.  
  3489. nybble        the first (lowest) or last(highest) group of 4 bits found in a:
  3490.  
  3491. byte          the fundamental 8 bit unit of our C64: an 8-bit computer.
  3492.  
  3493. word          two bytes side by side and related, ie. 16 bits. c64 pointers
  3494.               into RAM are lo/hi byte style.
  3495.  
  3496. bitmap        a contiguous block of data where a shape is defined when some
  3497.               bits or bit-pairs take a fore-ground color and others take on
  3498.               a background color.
  3499.  
  3500. color-ram     a block of data which defines the colors for the bitmap, 
  3501.               thus completing the picture.   
  3502.  
  3503. color nybble  since the C64 has a maximum of nybble 16 colors, to conserve 
  3504.               space 2 colors fit into 1 byte.
  3505.  
  3506. LORES         important! This would refer to pictures created by using the
  3507.               normal 256-byte character set. Extensive use of the graphics 
  3508.               characters in lowercase plus RVSon/RVSoff here. These are NOT 
  3509.               graphic files and are text files stored in SEQ format.
  3510.  
  3511. MEDRES        this refers to Koala Paint files and related formats.
  3512.  
  3513. HIRES         this refers to Doodle files and their derivatives.
  3514.  
  3515. #(A): Doodle!
  3516.  
  3517. This graphics format is the simplest of all! Here the screen is 
  3518. divided into 64000 pixels of light (320x200) and is truly HIRES. Neither 
  3519. the text color-ram at $D800 nor the 4 background colors at $D021 apply at 
  3520. all.  The downside is that only 2 colors can be displayed at one time in an 
  3521. 8x8 pixel block. This is the format geoPaint uses (but allows for a whole 
  3522. page displayed a screenful at a time). These files are prefixed with 
  3523. "dd..." that when compressed become "jj...". They are PRG files that load 
  3524. at $5C00. Internally, the 1K of color (1024 bytes) is first followed by 8K 
  3525. of bitmap (8192 bytes). The "dd..." files are invariably 37 blocks long, 
  3526. which makes sense since they are 9K long (36+ disk sectors each 254 
  3527. bytes).  The "1" bit of the bitmap uses the low nybble value of the 
  3528. color-ram while the "0" bit displays the high nybble color. 
  3529. Simple, straight-forward and direct! Some artists might find this 
  3530. color restriction too hazardous to their health. Since our screen is 
  3531. 320x200 pixels (64000 total remember?) dividing by 8 will give us only 
  3532. 8000 bytes needed for the bitmap and only 1000 bytes necessary for 
  3533. the color-ram. So this format actually wastes 216 bytes! Careful placement 
  3534. of colors can result in spectacular HIRES pictures though: look for 
  3535. the "Lobster" pic in geoPaint and the Doodle files "Middle Earth" 
  3536. and "Pagoda". Other related formats are (refer to the program "Autograph+" 
  3537. by Fuzzy Fox):
  3538.  
  3539. *  OCP Art Studio
  3540. *  RUN Paint HIRES
  3541. *  SID/PIC HIRES
  3542. *  (geoPaint)
  3543.  
  3544. #(A): Koala Paint
  3545.  
  3546. Koala is certainly the most colorful and interesting format. Here 
  3547. the screen is MEDRES, resulting in dots double pixel width for a resolution 
  3548. of 32000 elements (160x200). The loss of resol- ution is compensated by 
  3549. the ability to display 4 colors at once in each 8x8 pixel block. Here you 
  3550. have 2 blocks of color-ram, one wherever you put it AND the normal 
  3551. color-ram at $D800. Your picture is also effected screen-wide by 
  3552. the background color at $D021. These files, prefixed by  "[cbm-1]pic...", are
  3553. PRG files that load at $6000. The same files, when compressed, are prefixed 
  3554. by "gg...".  That first character in the filename of the raw format means that 
  3555. you cannot delete these files normally. It is made by pressing CBM-1 
  3556. (orange) and is hex $81 (decimal 129). The only way I know to scratch 
  3557. these files is by typing:
  3558.  
  3559.    OPEN15,DV,15,"s0:[cbm-1]pic...":close15
  3560.  
  3561. Where DV is your current device. Here the creators of Koala were smart 
  3562. and wasted NO space. Internally the file contains 8000 bytes for the 
  3563. bitmap(not 8192 bytes), 1000 bytes (not 1024) for the movable color-ram, 
  3564. 1000 bytes for the color-ram at $D800, and (this IS important) ONE more 
  3565. byte for the background color. The length ends up at 41 blocks which is 
  3566. ok considering it is about 10K long. These double width dots are called 
  3567. bit-pairs and they draw their colors from various sources:
  3568.  
  3569. %00 from the background color at $D021
  3570. %01 from the high nybble of the movable color-ram 
  3571. %10 from the low nybble of the movable color-ram 
  3572. %11 from the low nybble of the normal color-ram at $D800.
  3573.  
  3574. Interesting eh? There's your 4 colors and where they come from! Related
  3575. formats would be:
  3576.  
  3577. *  Advanced OCP Art Studio
  3578. *  Artist64
  3579. *  Blazing Paddles
  3580. *  RUN Paint MEDRES
  3581. *  SID/PIC multi-color
  3582.  
  3583. #(A): Conclusion
  3584.  
  3585. Although I am not an expert on graphics screens (not am I claiming to be),
  3586. I think programmers should be aware of these two poular formats for
  3587. storing and displaying graphics on the Commodore 64/128.  
  3588.           
  3589. ============================================================================
  3590.  
  3591. #(@)error: ? DS, DS$: rem The Error Channel
  3592.  
  3593. In Commodore Hacking Issue #10, the end of the "Second SID Chip Installation"
  3594. article was omitted.  The omitted section is included below. (SubRef: sid)
  3595.  
  3596. Certain early revisions of C=Hacking #10 are missing the end of the article
  3597. by Alan Jones entitled "Solving Large Systems of Linear Equations on a
  3598. C64 Without Memory".  The omitted text is included below. (SubRef: linear)
  3599.  
  3600. #(A)sid: Second SID Chip Installation (Line 137 on)
  3601.          (c) 1987 Mark A. Dickenson
  3602.  
  3603. Here comes the difficult part to explain.  This is the coupling
  3604. circuit for the audio output.  Here is a rough schematic.
  3605.  
  3606.  
  3607.  
  3608. Pin 27 on             12volts dc
  3609. SID chip   resistor    !
  3610. --.          10k ohm   !collector
  3611. 27!----.--/!/!/--.-----O 2n2222
  3612. --'    !         !     !emitter
  3613.        !         !     !
  3614.        <resistor !     !
  3615.        >1k       !     ! +
  3616.        <ohm      !     :--!]---to RCA
  3617.        !         !     !  10 uf
  3618.        !         !     !electrol cap
  3619.        !         !     !
  3620. ground---        !     !
  3621.        -         !     <resistor
  3622.                  !     >1k
  3623.                  !     <ohm
  3624.                  !     !
  3625.                  !     !
  3626.                  !     !
  3627.                  !    ---ground
  3628.                  !     -
  3629.                  !
  3630.                 === 1000 pf (.001mf)
  3631.                  !  capacitor
  3632.                  !
  3633.                 ---ground
  3634.                  -
  3635.  
  3636.  
  3637. You can get the 12 volts you need for the transistor directly from pin #28 of
  3638. the SID chip.
  3639.  
  3640. If you need any help on constructing this circuit check out any of the
  3641. many books that have schematics on the C-64.  This is similar to the one
  3642. already inside the C-64.
  3643.  
  3644. The ground wire from the RCA plug can be soldered to the main grounding
  3645. strip between the serial and video ports.  The center wire will be
  3646. connected to the negative side of the 10uf electrolitic capacitor.
  3647.  
  3648. I still think you should have someone familier with electronics install
  3649. this circuit for you.
  3650.  
  3651. If you have a problem with some cartridges, you will have to install
  3652. a switch between pin #25 of BOTH SID chips.  This will CUT the power to the
  3653. extra SID chip, effectivly turning it off.  I would suggest that you turn
  3654. OFF the computer before you turn the extra SID chip ON or OFF with this
  3655. switch.
  3656.  
  3657. A good place to mount the switch and RCA plug is on the back of the
  3658. computer and above the monitor jack on the 64.  I still haven't found a GOOD
  3659. place on the 128.  A suggestion was made that if you are not going to use
  3660. the RF output on the computer, you can cut the wire going to that RCA plug.
  3661. Then connect your audio output wire to the center connector of the plug.  This
  3662. does work but BE CAREFUL!
  3663.  
  3664. Good luck on the construction.
  3665.  
  3666.  
  3667. Mark A. Dickenson
  3668.  
  3669. #(A)linear: SOLVING LARGE SYSTEMS OF LINEAR EQUATIONS ON A C64 
  3670.             by Alan Jones  (alan.jones@qcs.org) WITHOUT MEMORY (Line 239 on)
  3671.  
  3672. PROC slv(n#,nr#,i#,REF a(),REF c(),REF b(,),sdb#,REF sw#(),REF fail#) CL
  3673. OSED
  3674.   // This routine solves a system of equations using the quartersolve
  3675.   // algorithm with partial pivoting.
  3676.   // It is called a "line at a time" and uses only
  3677.   // 0.25*nn memory locations which enables larger problems to be solved
  3678.  
  3679. Slv calls the swap'real and swap'integer proocedures from the strings
  3680. package.  The strings package is a ROMMED package on the Super Chip ROM.
  3681.  
  3682. It does exactly what it says, e.g.  swap'real(a,b) is the same as:
  3683. t:=a; a:=b; b:=t.
  3684.  
  3685. Slv calls the sdot, isamax#, sswap, sscal, saxpy, and scopy routines
  3686. from the blas package.  The blas package is LINKed to the program, but
  3687. it could, and should, be placed on EPROM.
  3688.  
  3689. Basic Linear Algebra Subroutines, BLAS
  3690.  
  3691. The BLAS were originally written for the Fortran language to speed
  3692. execution and streamline code used for solving linear algebra and other
  3693. matrix problems.  The LINPACK routines, Ref. 3, use the BLAS and are
  3694. perhaps the best known.  The idea is that the BLAS routines will be
  3695. highly optimized for a particular computer, coded in ML or a High Order
  3696. Language.  Some operating systems even include BLAS like routines.
  3697. Writing fast efficient programs is then a simple matter of selecting the
  3698. best solution algorithm and coding it in a manner that makes best use of
  3699. the blas routines.  There are blas routines for single precision, double
  3700. precision, and complex numbers.  The level 1 BLAS perform operations on
  3701. rows or columns of an array and typicaly do n scalar operations
  3702. replacing the inner most loop of code.  There are also level 2 BLAS that
  3703. perform n*n operations and Level 3 BLAS that perform n*n*n operations.
  3704. Nicholas Higham has coded most of the single precision level 1 blas
  3705. routines and put them in a Comal 2.0 package.  The Comal blas package is
  3706. included on the Packages Library Volume 2 disk.  I am not aware of ML
  3707. blas routines coded for any other C64/128 languages although this is
  3708. certainly possible and recommended.
  3709.  
  3710. The Comal blas routines behave exactly the same way that the Fortran
  3711. blas routines do except that Fortran can pass the starting address of an
  3712. array with just "a", while Comal requires "a(1)".  The Comal blas will
  3713. allow you pass an array, by reference, of single or multiple dimensions
  3714. and start from any position in the array.  If you code the blas routines
  3715. as ordinary Comal routines you have to pass additional parameters and
  3716. have separate routines for single dimensioned arrays and two dimensional
  3717. arrays.  Note also that Fortran stores two dimensional arrays by
  3718. columns, and Comal (like many other languages) stores two dimensional
  3719. arrays by rows.  If you translate code between Fortran and Comal using
  3720. blas routines you will have to change the increment variables.
  3721.  
  3722.             Fortran                          Comal
  3723.     dimension c(n), a(ilda,isda)     DIM c(n#), a(lda#,sda#)
  3724.     scopy(n,c,1,a(i,1),ilda)         scopy(n#,c(1),1,a(i#,1),1)
  3725.     scopy(n,c,1,a(1,j),1)            scopy(n#,c(1),1,a(1,j#),sda#)
  3726.  
  3727. The first scopy copies array c into the ith row of array a.  The second
  3728. scopy copies array c into the jth column of array a.
  3729.  
  3730. This is what scopy does in Fortran:
  3731.  
  3732.     subroutine scopy(n,sx,incx,sy,incy)
  3733.     real sx(1),sy(1)
  3734.     ix=1
  3735.     iy=1
  3736.     do 10 i = 1,n
  3737.       sy(iy) = sx(ix)
  3738.       ix = ix + incx
  3739.       iy = iy + incy
  3740.  10 continue
  3741.     return
  3742.     end
  3743.  
  3744. The Comal BLAS does exactly the same thing.  If coded entirely in COMAL
  3745. rather than as a package it would have to be different.  The call would
  3746. change.
  3747.  
  3748. scopy(n#,c(1),1,a(1,j#),sda#) would have to become,
  3749. scopy(n#,c(),1,1,a(,),1,j#,sda#,sda#) and the Comal procedure might be:
  3750.  
  3751. PROC scopy(n#, REF x(), ix#, incx#, REF y(,), iy#, jy#, sdy#, incy#) CLOSED
  3752.   iyinc#:=incy# DIV sdy#  //assuming y is dimensioned y(?,sdy#)
  3753.   jyinc#:=incy# MOD sdy#
  3754.   FOR i#=1 TO n# DO
  3755.     y(iy#,jy#):=x(ix#)
  3756.     ix#:+incx#; iy#:+iyinc#; jy#:+jyinc#
  3757.   ENDFOR
  3758. ENDPROC scopy
  3759.  
  3760. Note that more information has to be passed to the procedure and used
  3761. that the ML blas picks up automatically.  Also we would need separate
  3762. procedures to handle every combination of single and multi dimensional
  3763. arrays.  The Comal ML blas are indeed wonderful.  For speed
  3764. considerations this should also be left as an open procedure or better
  3765. yet just use in line code.
  3766.  
  3767. Here is a very simplified description of what each of the routines in
  3768. the Comal BLAS package does.
  3769.  
  3770. sum:=sasum(n#,x(1),1)  Returns sum of absolute values in x().
  3771.   sum:=0
  3772.   FOR i#:=1 TO n# DO sum:+ABS(x(i#))
  3773.  
  3774. saxpy(n#,sa,x(1),1,y(1),1)  Add a multiple of x() to y().
  3775.   FOR i#:=1 TO n# DO y(i#):+sa*x(i#)
  3776.  
  3777. prod:=sdot(n#,x(1),1,y(1),1)  Returns dot product of x() and y().
  3778.   prod:=0
  3779.   FOR i#:=1 TO n# DO prod:+x(i#)*y(i#)
  3780.  
  3781. sswap(n#,x(1),1,y(1),1)  Swaps x() and y().
  3782.   FOR i#:=1 TO n# DO t:=x(i#); x(i#):=y(i#); y(i#):=t
  3783.  
  3784. scopy(n#,x(1),1,y(1),1)  Copy x() to y().
  3785.   For i#:=1 TO n# DO y(i#):=x(i#)
  3786.  
  3787. max#:=isamax#(n,x(1),1)  Returns index of the element of x() with the
  3788.                          largest absolute value.
  3789.   t:=0; max#:=1
  3790.   FOR i#:=1 TO n#
  3791.     IF ABS(x(i#))>t THEN t:=ABS(x(i#)); max#:=i#
  3792.   ENDFOR i#
  3793.  
  3794. sscal(n#,sa,x(1),1)  Scale x() by a constant sa.
  3795.   FOR i#:=1 TO n# DO x(i#):=sa*x(i#)
  3796.  
  3797. snrm2(n#,x(1),1)  Returns the 2 norm of x().
  3798.   norm2:=0
  3799.   FOR i#:=1 TO n# DO norm2:+x(i#)*x(i#)
  3800.   norm2:=SQR(norm2)
  3801.  
  3802. srot(n#,x(1),1,y(1),1,c,s)  Apply Givens rotation.
  3803.   FOR i#:=1 TO n# DO
  3804.     t:=c*x(i#) + s*y(i#)
  3805.     y(i#):=s*x(i#) + c*y(i#)
  3806.     x(i#):=t
  3807.   ENDFOR i#
  3808.  
  3809.  
  3810. Bear in mind that each of these simple examples can be more complex as
  3811. was given for scopy.  You now have enough information to write your own
  3812. BLAS routines in ML or the programming language of your choice, or to
  3813. expand the BLAS routine calls in slv to ordinary in line code.
  3814.  
  3815. You can also apply the BLAS routines in creative ways besides just
  3816. operating on rows or columns.  For example you could create the identity
  3817. matrix with:
  3818.  
  3819.   DIM a(n#,n#)
  3820.   a(1,1):=1; a(1,2):=0
  3821.   scopy(n#*n#-2,a(1,2),0,a(1,3),1) // zero the rest of the matrix
  3822.   scopy(n#-1,a(1,1),0,a(2,2),n#+1) // copy ones to the diagonal.
  3823.  
  3824. References
  3825.  
  3826. 1.  Zambardino, R. A., "Solutions of Systems of Linear Equations with
  3827. Partial Pivoting and Reduced Storage Requirements", The Computer Journal
  3828. Vol. 17, No. 4, 1974, pp. 377-378.
  3829.  
  3830. 2.  Orden A., "Matrix Inversion and Related Topics by Direct Methods",
  3831. in Mathematical Methods for Digital Computers, Vol. 1, Edited by A.
  3832. Ralston and H. Wilf, John Wiley and Sons Inc.,  1960.
  3833.  
  3834. 3.  Dongarra, J. J., Moeler, C. B., Bunch, J. R., Stewart, G. W.,
  3835. Linpack Users' Guide, SIAM Press, Philadelphia, 1979.
  3836.  
  3837. ============================================================================
  3838.  
  3839. #(@)next: The Next Hack
  3840.  
  3841. "But wait, there's more!"  Actually, there is, but you'll have to wait
  3842. until next issue for it.  Here's a little appetizer of what's ahead in
  3843. Commodore Hacking issue #12
  3844.  
  3845. o  All you cross-development folks, listen up!  Issue #12 will enter the
  3846.    realm of cross-compilers with Craig Bruce as he details the construction
  3847.    of a high level language cross compiler.  It'll be written in C and will
  3848.    compile a a simplified but structured custom language including concepts
  3849.    from BASIC, C, and Pascal. Concepts like declaration handling, expression 
  3850.    interpretion and optimization, and structure control definitions will be
  3851.    discussed
  3852.  
  3853. o  Gearing up for the 65C816S.  C=Hacking will detail the new opcodes
  3854.    available to programmers, show how to detect CPU clock speed on any
  3855.    C64, accelerated or not, discuss pitfalls in code migration, and 
  3856.    possibly give a rundown on a prototype accelerator unit from CMD.
  3857.    
  3858. o  SLIP, Sliding away....  C=Hacking will take an in-depth look at Daniel
  3859.    Dallmann's SLIP-DEMO program and go over the SLIP and TCP/IP 
  3860.    protocols in detail as they relate to the Commodore.
  3861.    
  3862. o  Here Boy, here Boy! Good Dog.  The "FIDO's Nuggets" column will bring
  3863.    readers up to date on the discussions in the FIDO CBM echo.
  3864.  
  3865. o  The RumorMonger.  The best rumors we've heard so far.  Your mileage
  3866.    may vary...
  3867.  
  3868. o  All that and C=Hacking's regular columns.  
  3869.  
  3870. So, set aside a place on that disk drive for the next issue now, because you 
  3871. won't want to miss it...
  3872.  
  3873. ============================================================================
  3874. #(@)bottom